stratagus-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Stratagus-CVS] stratagus data/ccl/ai.ccl src/ai/ai_force.c src...


From: ludovic pollet
Subject: [Stratagus-CVS] stratagus data/ccl/ai.ccl src/ai/ai_force.c src...
Date: Fri, 31 Oct 2003 04:14:49 -0500

CVSROOT:        /cvsroot/stratagus
Module name:    stratagus
Branch:         
Changes by:     ludovic pollet <address@hidden> 03/10/31 04:14:48

Modified files:
        data/ccl       : ai.ccl 
        src/ai         : ai_force.c ai_local.h ai_resource.c ai_rules.c 
                         ccl_ai.c new_ai.c 
        src/clone      : ccl.c clone.c 
        src/game       : loadgame.c 
        src/include    : ai.h ccl.h 

Log message:
        Fix for debugcheck in AiRemoveFromBuilded and others

Patches:
Index: stratagus/data/ccl/ai.ccl
diff -u stratagus/data/ccl/ai.ccl:1.57 stratagus/data/ccl/ai.ccl:1.58
--- stratagus/data/ccl/ai.ccl:1.57      Mon Oct 27 05:33:45 2003
+++ stratagus/data/ccl/ai.ccl   Fri Oct 31 04:14:41 2003
@@ -26,7 +26,7 @@
 ;;      along with this program; if not, write to the Free Software
 ;;      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  
USA
 ;;
-;;     $Id: ai.ccl,v 1.57 2003/10/27 10:33:45 pludov Exp $
+;;     $Id: ai.ccl,v 1.58 2003/10/31 09:14:41 pludov Exp $
 
 ;(define (ai:sleep) () #t)
 
@@ -129,9 +129,7 @@
     (list 'unit-equiv 'unit-knight
        'unit-paladin)
     (list 'unit-equiv 'unit-peasant)
-    (list 'unit-equiv 'unit-human-oil-tanker)
-    (list 'unit-equiv 'unit-alliance-watch-tower
-        'unit-alliance-guard-tower 'unit-alliance-cannon-tower) )
+    (list 'unit-equiv 'unit-human-oil-tanker) )
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;     * Race orc.
@@ -218,9 +216,7 @@
     (list 'unit-equiv 'unit-ogre
        'unit-ogre-mage)
     (list 'unit-equiv 'unit-peon)
-    (list 'unit-equiv 'unit-orc-oil-tanker)
-    (list 'unit-equiv 'unit-mythical-watch-tower
-        'unit-mythical-guard-tower 'unit-mythical-cannon-tower) )
+    (list 'unit-equiv 'unit-orc-oil-tanker) )
 
 ;;=============================================================================
 ;;
@@ -308,41 +304,39 @@
 ;;
 
 
-(define-ai-action '(defense attack)
-    '(
-       (
-           availables-orc-units
-           ai:send-all:get-needs
-           ai:default-defend
-       )
-       (
-               unit-ogre-mage
-               unit-ogre
-               unit-catapult   
-               unit-axethrower 
-               unit-berserker
-               unit-grunt
-               unit-death-knight
-               unit-dragon))
-)
-
-(define-ai-action '(defense attack)
-    '(
-       (
-           availables-human-units
-           ai:send-all:get-needs
-           ai:default-defend
-       )
-       (
-               unit-paladin    
-               unit-knight     
-               unit-ballista
-               unit-ranger
-               unit-archer
-               unit-footman
-               unit-mage
-               unit-gryphon-rider))
-)
+;;(define-ai-action '(defense attack)
+;;    '(
+;;     (
+;;         availables-orc-units
+;;         ai:send-all:get-needs
+;;         ai:default-defend
+;;     )
+;;     (
+;;             unit-ogre-mage
+;;             unit-ogre
+;;             unit-catapult   
+;;             unit-axethrower 
+;;             unit-berserker
+;;             unit-grunt
+;;             unit-death-knight
+;;             unit-dragon))
+;;)
+
+;;(define-ai-action '(defense attack)
+;;    '(
+;;     (
+;;         availables-human-units
+;;         ai:send-all:get-needs
+;;         ai:default-defend
+;;     )
+;;     (
+;;             unit-knight     
+;;             unit-ballista
+;;             unit-archer
+;;             unit-footman
+;;             unit-mage
+;;             unit-gryphon-rider))
+;;)
 
 ;; Define the script's properties ( rules used to choose a script... ) 
 (define-ai-action '(defense attack)
@@ -361,7 +355,7 @@
     
     ;; Global force requirement ( percentages ).
     ;; Must send unit of at least this force... ( can remove allied force ... )
-    (force-minimum (enemy-hotspot-ground-force 100) )
+    (force-minimum (enemy-hotspot-ground-force 100) (enemy-map-ground-force 
20))
     
     ;; force requirements in units ( percentages )
     ((ai:soldier) (enemy-hotspot-ground-force 110))
@@ -383,7 +377,7 @@
     
     ;; Global force requirement ( percentages ).
     ;; Must send unit of at least this force... ( can remove allied force ... )
-    (force-minimum (enemy-hotspot-ground-force 200) )
+    (force-minimum (enemy-hotspot-ground-force 200) (enemy-map-ground-force 
20))
 
     ;; force requirements in units ( percentages )
     ((ai:worker) (enemy-hotspot-ground-force 110))))
@@ -404,7 +398,7 @@
     
     ;; Global force requirement ( percentages ).
     ;; Must send unit of at least this force... ( can remove allied force ... )
-    (force-minimum (enemy-hotspot-air-fire 110)        )
+    (force-minimum (enemy-hotspot-air-fire 110)        (enemy-map-air-force 
25))
     
     ;; force requirements in units ( percentages )
     ((ai:flyer) 
@@ -423,7 +417,7 @@
            ai:default-defend
        )
        (zero-gauges)
-       (force-minimum (enemy-hotspot-sea-force 100) )
+       (force-minimum (enemy-hotspot-sea-force 100) (enemy-map-sea-force 25))
        ((ai:battleship)
            (enemy-hotspot-sea-fire 70)
            (enemy-hotspot-ground-force 30) (enemy-hotspot-sea-force 30))
@@ -441,7 +435,7 @@
            ai:default-defend
        )
        (zero-gauges enemy-hotspot-detectors)
-       (force-minimum (enemy-hotspot-sea-force 50))
+       (force-minimum (enemy-hotspot-sea-force 50) (enemy-map-sea-force 25))
        ((ai:submarine) (enemy-hotspot-sea-force 50))
        ))
 
@@ -455,12 +449,12 @@
            ai:default-defend
        )
        
-       ;; gauge which must be 0..          
+       ;; gauge which must be 0...         
        (zero-gauges enemy-hotspot-air-force enemy-hotspot-sea-force)
     
        ;; Global force requirement ( percentages ).
        ;; Must send unit of at least this force... ( can remove allied force 
... )
-       (force-minimum (enemy-hotspot-ground-force 100) )
+       (force-minimum (enemy-hotspot-ground-force 100) (enemy-map-ground-force 
25))
        
        ;; force requirements in units ( percentages )
        ((ai:cavalrie) (enemy-hotspot-ground-force 130))    
@@ -475,18 +469,19 @@
            ;; Ai Script to execute when ready
            ai:default-defend
        )
-       ;; gauge which must be 0..          
+       ;; gauge which must be 0...
        (zero-gauges enemy-hotspot-sea-force)
     
        ;; Global force requirement ( percentages ).
        ;; Must send unit of at least this force... ( can remove allied force 
... )
-       (force-minimum (enemy-hotspot-ground-force 100) 
(enemy-hotspot-air-force 100) )
+       (force-minimum (enemy-hotspot-ground-force 100) 
(enemy-hotspot-air-force 100) 
+                       (enemy-map-ground-force 25) (enemy-map-air-force 25))
     
        ;; force requirements in units ( percentages )
-       ((ai:cavalrie)  (enemy-hotspot-ground-force 75))
-       ((ai:soldier)   (enemy-hotspot-ground-force 20))
        ((ai:shooter)   (enemy-hotspot-ground-force 25)
                        (enemy-hotspot-air-force 120))
+       ((ai:cavalrie)  (enemy-hotspot-ground-force 75))
+       ((ai:soldier)   (enemy-hotspot-ground-force 20))
     ))
 
 (define-ai-action '(defense attack)    
@@ -499,10 +494,11 @@
            ai:default-defend
        )
        (zero-gauges enemy-hotspot-sea-force)
-       (force-minimum  (enemy-hotspot-ground-force 100) 
(enemy-hotspot-air-force 100) )
-       ((ai:soldier)   (enemy-hotspot-ground-force 80))
+       (force-minimum  (enemy-hotspot-ground-force 100) 
(enemy-hotspot-air-force 100) 
+                       (enemy-map-ground-force 25) (enemy-map-air-force 25))
        ((ai:shooter)   (enemy-hotspot-ground-force 40)
                        (enemy-hotspot-air-force 120))
+       ((ai:soldier)   (enemy-hotspot-ground-force 80))
     ))
 
 ;;
@@ -755,8 +751,10 @@
     (ai:need 'unit-mythical-blacksmith)
 ;;    (ai:force 1 'unit-grunt 1)
     (ai:force 0 'unit-grunt 1)
+    (ai:force 1 'unit-grunt 2)
 ;;    (ai:wait-force 1)                ;; wait until attack party is completed
 ;;    (ai:attack-with-force 1)
+    (ai:sleep 20)
 
     (ai:force 0 'unit-grunt 2)
     (ai:research 'upgrade-battle-axe1)
@@ -765,6 +763,7 @@
     (ai:research 'upgrade-orc-shield2)
     (ai:set  'unit-peon 20)
     (ai:force 0 'unit-grunt 6)
+    (ai:force 1 'unit-grunt 6)
 ;;    (ai:wait-force 1)                ;; wait until attack party is completed
     (ai:set 'unit-mythical-barracks 3)
     (ai:force 0 'unit-grunt 20)
@@ -1442,7 +1441,7 @@
     (ai:upgrade-to (ai:guard-tower))
     (ai:need (ai:airport))
     (ai:set  (ai:worker) 20)
-;;    (ai:force 1 (ai:flyer) 2)
+    (ai:force 1 (ai:flyer) 4)
 ;;    (ai:attack-with-force 2)
 
     (ai:sleep 500)
@@ -1612,7 +1611,7 @@
     (ai:sleep 500)
     (ai:research (ai:upgrade-catapult-1))
     (ai:need (ai:cavalry))
-    (ai:force 0 (ai:soldier) 3 (ai:catapult) 1 (ai:scout) 1 (ai:submarine) 1 
(ai:destroyer) 2 (ai:battleship) 1 )    
+    (ai:force 0 (ai:soldier) 3 (ai:catapult) 1 (ai:scout) 1 (ai:submarine) 1 
(ai:destroyer) 2 (ai:battleship) 1 )
     (ai:force 1 (ai:scout) 1 (ai:destroyer) 2 (ai:battleship) 2)
     
     (ai:sleep 3000)
@@ -1664,8 +1663,7 @@
 ;;
 (define ai:human-land-attack-endloop
   '((writes nil "Looping !\n")
-    (ai:force 0 'unit-footman 2 'unit-ranger 4 'unit-paladin 8 'unit-ballista 2
-       'unit-mage 6 'unit-gryphon-rider 3)
+    (ai:force 0 'unit-footman 2 'unit-ranger 4 'unit-paladin 8 'unit-ballista 
2        'unit-mage 6 'unit-gryphon-rider 3)
 
     (ai:sleep 500)
     (ai:script ai:human-land-attack-endloop) ) )
@@ -1682,7 +1680,8 @@
     (ai:set  'unit-peasant 4)
     (ai:need 'unit-elven-lumber-mill)
     (ai:need 'unit-alliance-barracks)
-    (ai:force 0  'unit-footman 3)
+    (ai:force 0 'unit-footman 3)
+    (ai:force 1 'unit-footman 4)
 
     (ai:set  'unit-peasant 9)
     (ai:sleep  500)
@@ -1703,6 +1702,7 @@
     (ai:sleep  500)
     (ai:set  'unit-peasant 15)
     (ai:force 0 'unit-footman 6 'unit-archer 3 'unit-ballista 1)
+    (ai:force 1 'unit-footman 6 'unit-archer 3 'unit-ballista 1)
 
     (ai:sleep  500)
     (ai:upgrade-to 'unit-keep)
Index: stratagus/src/ai/ai_force.c
diff -u stratagus/src/ai/ai_force.c:1.36 stratagus/src/ai/ai_force.c:1.37
--- stratagus/src/ai/ai_force.c:1.36    Sun Oct 26 10:34:58 2003
+++ stratagus/src/ai/ai_force.c Fri Oct 31 04:14:45 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: ai_force.c,v 1.36 2003/10/26 15:34:58 pludov Exp $
+//      $Id: ai_force.c,v 1.37 2003/10/31 09:14:45 pludov Exp $
 
 //@{
 
@@ -45,17 +45,145 @@
 #include "ai_local.h"
 #include "actions.h"
 #include "map.h"
+#include "depend.h"
 
 /*----------------------------------------------------------------------------
 --     Variables
 ----------------------------------------------------------------------------*/
 
+global int UnitTypeEquivs[UnitTypeMax + 1];/// equivalence between unittypes
+
 /*----------------------------------------------------------------------------
 --     Functions
 ----------------------------------------------------------------------------*/
 
 
 /**
+**     Remove any equivalence between unittypes
+*/
+global void AiResetUnitTypeEquiv(void)
+{
+    int i;
+    for (i = 0; i <= UnitTypeMax; i++) {
+       UnitTypeEquivs[i] = i;
+    }
+}
+
+/**
+**     Make two unittypes equivalents from the AI's point of vue
+**
+**     @param a        the first unittype
+**     @param b        the second unittype
+*/
+global void AiNewUnitTypeEquiv(UnitType * a,UnitType * b)
+{
+    int find,replace,i;
+    
+    find = UnitTypeEquivs[a->Type];
+    replace = UnitTypeEquivs[b->Type];
+    
+    // Always record equivalences with the lowest unittype.
+    if (find < replace) {
+       i = find;
+       find = replace;
+       replace = i;
+    }
+    
+    // Then just find & replace in UnitTypeEquivs...
+    for (i = 0; i <= UnitTypeMax; i++) {
+       if (UnitTypeEquivs[i] == find) {
+           UnitTypeEquivs[i] = replace;
+       }
+    }
+}
+
+
+/**
+**     Find All unittypes equivalent to a given one
+**
+**     @param unittype the unittype to find equivalence for
+**     @param result   int array which will hold the result. (Size 
UnitTypeMax+1)
+**     @return         the number of unittype found
+*/
+global int AiFindUnitTypeEquiv(const UnitType * unittype,int * result)
+{
+    int i;
+    int search;
+    int count;
+
+    search = UnitTypeEquivs[unittype->Type];
+    count = 0;
+
+    for (i = 0; i < UnitTypeMax + 1; i++) {
+       if (UnitTypeEquivs[i] == search) {
+           // Found one
+           result[count] = i;
+           count++;
+       }
+    }
+
+    return count;
+}
+
+/**
+**     Find All unittypes equivalent to a given one, and which are available
+**     UnitType are returned in the prefered order ( ie palladin >> knight... )
+**
+**     @param unittype the unittype to find equivalence for
+**     @param result   int array which will hold the result. (Size 
UnitTypeMax+1)
+**     @return         the number of unittype found
+*/
+global int AiFindAvailableUnitTypeEquiv(const UnitType * unittype,int * 
usableTypes)
+{
+    int usableTypesCount;
+    int i, j;
+    int tmp;
+    int playerid;
+    int bestlevel, curlevel;
+
+    // 1 - Find equivalents
+    usableTypesCount = AiFindUnitTypeEquiv(unittype,  usableTypes);
+
+    // 2 - Remove unavailable unittypes
+    for (i = 0; i < usableTypesCount; ) {
+       if (! CheckDependByIdent(AiPlayer->Player, 
UnitTypes[usableTypes[i]]->Ident)) {
+           // Not available, remove it
+           usableTypes[i] = usableTypes[usableTypesCount - 1];
+           usableTypesCount--;
+       } else {
+           i++;
+       }
+    }
+
+    // 3 - Sort by level
+    playerid = AiPlayer->Player->Player;
+
+    // We won't have usableTypesCount>4, so simple sort should do it
+    for (i = 0; i < usableTypesCount-1; i++) {
+       bestlevel = UnitTypes[usableTypes[i]]->Priority;
+       for (j = i + 1; j < usableTypesCount; j++) {
+           curlevel = UnitTypes[usableTypes[j]]->Priority;
+           
+           if (curlevel > bestlevel) {
+               // Swap
+               tmp = usableTypes[j];
+               usableTypes[j] = usableTypes[i];
+               usableTypes[i] = tmp;
+               
+               bestlevel = curlevel;
+           }
+       }
+    }
+    DebugLevel0Fn("prefered order for %s is " _C_ unittype->Ident);
+    for (i = 0; i < usableTypesCount; i++) {
+       DebugLevel0(" %s" _C_ UnitTypes[usableTypes[i]]->Ident);
+    }
+    DebugLevel0("\n");
+    
+    return usableTypesCount;
+}
+
+/**
 **     Count available units by type in a force.
 **
 **     The returned array will map UnitType=>number of unit
@@ -69,12 +197,11 @@
     AiUnit *aiunit;
     memset(countByType, 0, sizeof (int) * (UnitTypeMax + 1));
 
-    // FIXME: Should I use equivalent unit types?
     aiunit = AiPlayer->Force[force].Units;
     while (aiunit) {
        if ((!aiunit->Unit->Destroyed) &&
            (aiunit->Unit->HP) && (aiunit->Unit->Orders[0].Action != 
UnitActionDie)) {
-           type = aiunit->Unit->Type->Type;
+           type = UnitTypeEquivs[aiunit->Unit->Type->Type];
 
            DebugCheck((type < 0) || (type > UnitTypeMax));
            countByType[type]++;
@@ -93,14 +220,16 @@
 global int AiForceSubstractWant(int force, int *countByType)
 {
     int missing;
+    int type;
     const AiUnitType *aitype;
 
     missing = 0;
     aitype = AiPlayer->Force[force].UnitTypes;
     while (aitype) {
-       countByType[aitype->Type->Type] -= aitype->Want;
-       if (countByType[aitype->Type->Type] < 0) {
-           missing -= countByType[aitype->Type->Type];
+       type=UnitTypeEquivs[aitype->Type->Type];
+       countByType[type] -= aitype->Want;
+       if (countByType[type] < 0) {
+           missing -= countByType[type];
        }
        aitype = aitype->Next;
     }
@@ -111,6 +240,8 @@
 /**
 **     Complete dst force with units from src force.
 **
+**     FIXME : should check that unit can reach dst force's hotspot.
+**
 **     @param src the force from which units are taken
 **     @param dst the force into which units go
 */
@@ -118,7 +249,7 @@
 {
     AiUnit **prev;
     AiUnit *aiunit;
-
+    int type;
     int counter[UnitTypeMax + 1];
 
     //
@@ -133,18 +264,20 @@
        // Nothing missing => abort.
        return;
     }
+
     // Iterate the source force, moving needed units into dest...
     prev = &AiPlayer->Force[src].Units;
     while (*prev) {
        aiunit = (*prev);
-       if (counter[aiunit->Unit->Type->Type] < 0) {
+       type = UnitTypeEquivs[aiunit->Unit->Type->Type];
+       if (counter[type] < 0) {
            // move in dest force...
            *prev = aiunit->Next;
 
            aiunit->Next = AiPlayer->Force[dst].Units;
            AiPlayer->Force[dst].Units = aiunit;
 
-           counter[aiunit->Unit->Type->Type]++;
+           counter[type]++;
        } else {
            // Just iterate
            prev = &aiunit->Next;
@@ -248,6 +381,10 @@
 
     aiu = AiPlayer->Force[force].Units;
     while (aiu) {
+       // Decrease usage count
+       RefsDebugCheck(!aiu->Unit->Refs);
+       --aiu->Unit->Refs;
+
        next_u = aiu->Next;
        free(aiu);
        aiu = next_u;
@@ -284,6 +421,7 @@
 {
     int counter[UnitTypeMax + 1];
     int missing;
+    int realtype;
 
     //
     //  Count units in force.
@@ -296,10 +434,12 @@
     missing = AiForceSubstractWant(force, counter);
     AiPlayer->Force[force].Completed = (missing == 0);
 
-    if (counter[type->Type] < 0) {
+    realtype = UnitTypeEquivs[type->Type];
+
+    if (counter[realtype] < 0) {
        // Ok we will put this unit in this force !
-       // Just one missing...
-       if ((counter[type->Type] == -1) && (missing == 1)) {
+       // Just one missing ?
+       if ((counter[realtype] == -1) && (missing == 1)) {
            AiPlayer->Force[force].Completed = 1;
        }
        return 1;
@@ -381,6 +521,9 @@
 
 /**
 **     Enrole a unit in the specific force.
+**     Does not take equivalence into account
+**
+**     FIXME : currently iterate all units (slow)
 **     FIXME : should take units which are closer to the hotspot.
 **     FIXME : should ensure that units can move to the hotspot.
 **
@@ -413,8 +556,7 @@
        aiUnit = AiPlayer->Force[src_force].Units;
        prev = &AiPlayer->Force[src_force].Units;
        while (aiUnit) {
-           // FIXME : comparaison should match equivalent unit as well
-           if (aiUnit->Unit->Type == ut) {
+           if (aiUnit->Unit->Type->Type == ut->Type) {
                *prev = aiUnit->Next;
 
                // Move to dstForce 
@@ -441,15 +583,17 @@
 local void AiFinalizeForce(int force)
 {
     int i;
+    int type;
     int unitcount[UnitTypeMax + 1];
     AiUnitType *aitype;
 
     AiForceCountUnits(force, unitcount);
     aitype = AiPlayer->Force[force].UnitTypes;
     while (aitype) {
-       if (unitcount[aitype->Type->Type] > aitype->Want) {
-           aitype->Want = unitcount[aitype->Type->Type];
-           unitcount[aitype->Type->Type] = 0;
+       type = UnitTypeEquivs[aitype->Type->Type];
+       if (unitcount[type] > aitype->Want) {
+           aitype->Want = unitcount[type];
+           unitcount[type] = 0;
        }
        aitype = aitype->Next;
     }
@@ -480,35 +624,59 @@
     int id, maxPower, forceUpdated;
     UnitType *ut;
     int curpower[3];
+    int maxadd;
+    int lefttoadd;
+    int unittypeforce;
+    int equivalents[UnitTypeMax + 1];
+    int equivalentscount;
+    int equivalentid;
 
     curpower[0] = power[0];
     curpower[1] = power[1];
     curpower[2] = power[2];
     AiEraseForce(AiScript->ownForce);
 
+    
+
     do {
        forceUpdated = 0;
        maxPower = (curpower[0] > curpower[1] ?
            (curpower[0] > curpower[2] ? 0 : 2) : (curpower[1] > curpower[2] ? 
1 : 2));
 
        for (id = 0; id < unittypescount; id++) {
-           ut = UnitTypes[unittypes[id]];
-           if (!(ut->CanTarget & (1 << maxPower))) {
-               continue;
-           }
-           // Try to respond to the most important power ...
-           if (AiEnroleSpecificUnitType(AiScript->ownForce, ut, 1) == 1) {
-               continue;
-           }
+           // Search in equivalents
+           equivalentscount = 
AiFindAvailableUnitTypeEquiv(UnitTypes[unittypes[id]], equivalents);
+           for (equivalentid = 0; equivalentid < equivalentscount; 
equivalentid++) {
+               ut = UnitTypes[equivalents[equivalentid]];
+               if (!(ut->CanTarget & (1 << maxPower))) {
+                   continue;
+               }
+
+               unittypeforce = AiUnittypeForce(ut) / 8;
+               unittypeforce = (unittypeforce ? unittypeforce : 1);
+
+               // Try to respond to the most important power ...
+               maxadd = 1 + curpower[maxPower] / unittypeforce;
+
+               lefttoadd = AiEnroleSpecificUnitType(AiScript->ownForce, ut, 
maxadd);
 
-           curpower[maxPower] -= AiUnittypeForce(ut);
-           forceUpdated = 1;
-           maxPower = (curpower[0] > curpower[1] ?
-               (curpower[0] > curpower[2] ? 0 : 2) :
-               (curpower[1] > curpower[2] ? 1 : 2));
-           if (curpower[maxPower] <= 0) {
-               AiFinalizeForce(AiScript->ownForce);
-               return 0;
+               // Nothing added, continue.
+               if (lefttoadd == maxadd) {
+                   continue;
+               }
+
+               // FIXME : don't always use the right unittype here...
+               curpower[maxPower] -= (maxadd - lefttoadd) * unittypeforce;
+               
+               forceUpdated = 1;
+               
+               maxPower = (curpower[0] > curpower[1] ?
+                   (curpower[0] > curpower[2] ? 0 : 2) :
+                   (curpower[1] > curpower[2] ? 1 : 2));
+               if (curpower[maxPower] <= 0) {
+                   AiFinalizeForce(AiScript->ownForce);
+                   return 0;
+               }
            }
        }
     } while (forceUpdated);
@@ -950,7 +1118,7 @@
            return;
 
        case AiForceHelpForce:
-           // Send all idles units to help
+           // Send all idles units in the attacked force for help
            rescue = aiForce->Units;
            while (rescue) {
                // TODO : check that dead units does appear there
Index: stratagus/src/ai/ai_local.h
diff -u stratagus/src/ai/ai_local.h:1.39 stratagus/src/ai/ai_local.h:1.40
--- stratagus/src/ai/ai_local.h:1.39    Wed Oct 29 18:11:53 2003
+++ stratagus/src/ai/ai_local.h Fri Oct 31 04:14:45 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: ai_local.h,v 1.39 2003/10/29 23:11:53 pludov Exp $
+//      $Id: ai_local.h,v 1.40 2003/10/31 09:14:45 pludov Exp $
 
 #ifndef __AI_LOCAL_H__
 #define __AI_LOCAL_H__
@@ -228,7 +228,7 @@
 */
 struct _ai_action_evaluation_ {
     AiScriptAction*    aiScriptAction; /// Action evaluated
-
+    int                        gamecycle;      /// Gamecycle when this 
evaluation occured
     int                        hotSpotX;       /// X position of the hotspot, 
or -1
     int                        hotSpotY;       /// Y position of the hotspot, 
or -1
 
@@ -372,7 +372,7 @@
 #define MaxAiScriptActions     64      /// How many AiScriptActions are 
supported
 extern int AiScriptActionNum;          /// Current number of AiScriptAction
 extern AiScriptAction AiScriptActions[MaxAiScriptActions];/// All availables 
AI script actions   
-
+extern int UnitTypeEquivs[UnitTypeMax + 1];/// equivalence between unittypes
 extern PlayerAi* AiPlayer;             /// Current AI player
 extern AiRunningScript* AiScript;      /// Currently running script
 extern char** AiTypeWcNames;           /// pud num to internal string mapping
@@ -396,6 +396,14 @@
 extern void AiExplore(int x, int y, int exploreMask);
     /// Count the number of builder unit available for the given unittype 
 extern int AiCountUnitBuilders(UnitType * type);
+    /// Make two unittypes be considered equals
+extern void AiNewUnitTypeEquiv(UnitType * a,UnitType * b);
+    /// Remove any equivalence between unittypes
+extern void AiResetUnitTypeEquiv(void);
+    /// Finds all equivalents units to a given one
+extern int AiFindUnitTypeEquiv(const UnitType * i,int * result);
+    /// Finds all available equivalents units to a given one, in the prefered 
order
+extern int AiFindAvailableUnitTypeEquiv(const UnitType * i,int * result);
 
 //
 //      Buildings
Index: stratagus/src/ai/ai_resource.c
diff -u stratagus/src/ai/ai_resource.c:1.75 stratagus/src/ai/ai_resource.c:1.76
--- stratagus/src/ai/ai_resource.c:1.75 Wed Oct 29 18:11:54 2003
+++ stratagus/src/ai/ai_resource.c      Fri Oct 31 04:14:45 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: ai_resource.c,v 1.75 2003/10/29 23:11:54 pludov Exp $
+//      $Id: ai_resource.c,v 1.76 2003/10/31 09:14:45 pludov Exp $
 
 //@{
 
@@ -469,49 +469,61 @@
     const int *unit_count;
     AiUnitTypeTable *const *tablep;
     const AiUnitTypeTable *table;
-
+    
+    int usableTypes[UnitTypeMax+1];
+    int usableTypesCount;
+    int currentType;
+    
     DebugLevel3Fn(":%s\n" _C_ type->Name);
 
-    //
-    //  Check if we have a place for building or an unit to build.
-    //
-    if (type->Building) {
-       n = AiHelpers.BuildCount;
-       tablep = AiHelpers.Build;
-    } else {
-       n = AiHelpers.TrainCount;
-       tablep = AiHelpers.Train;
-    }
-    if (type->Type > n) {              // Oops not known.
-       DebugLevel0Fn("Nothing known about `%s'\n" _C_ type->Ident);
-       return 0;
-    }
-    table = tablep[type->Type];
-    if (!table) {                      // Oops not known.
-       DebugLevel0Fn("Nothing known about `%s'\n" _C_ type->Ident);
-       return 0;
-    }
-    n = table->Count;
+    // Find equivalents unittypes.
+    usableTypesCount = AiFindAvailableUnitTypeEquiv(type, usableTypes);
+    
+    // Iterate them
+    for (currentType = 0; currentType < usableTypesCount; currentType++) {
+
+       type = UnitTypes[usableTypes[currentType]];
 
-    unit_count = AiPlayer->Player->UnitTypesCount;
-    for (i = 0; i < n; ++i) {
        //
-       //      The type for builder/trainer is available
+       //  Check if we have a place for building or an unit to build.
        //
-       if (unit_count[table->Table[i]->Type]) {
-           DebugLevel3("Found a builder for a %s.\n" _C_ type->ident);
-           if (type->Building) {
-               if (AiBuildBuilding(table->Table[i], type)) {
-                   return 1;
-               }
-           } else {
-               if (AiTrainUnit(table->Table[i], type)) {
-                   return 1;
+       if (type->Building) {
+           n = AiHelpers.BuildCount;
+           tablep = AiHelpers.Build;
+       } else {
+           n = AiHelpers.TrainCount;
+           tablep = AiHelpers.Train;
+       }
+       if (type->Type > n) {           // Oops not known.
+           DebugLevel0Fn("Nothing known about `%s'\n" _C_ type->Ident);
+           continue;
+       }
+       table = tablep[type->Type];
+       if (!table) {                   // Oops not known.
+           DebugLevel0Fn("Nothing known about `%s'\n" _C_ type->Ident);
+           continue;
+       }
+       n = table->Count;
+
+       unit_count = AiPlayer->Player->UnitTypesCount;
+       for (i = 0; i < n; ++i) {
+           //
+           //      The type for builder/trainer is available
+           //
+           if (unit_count[table->Table[i]->Type]) {
+               DebugLevel3("Found a builder for a %s.\n" _C_ type->ident);
+               if (type->Building) {
+                   if (AiBuildBuilding(table->Table[i], type)) {
+                       return 1;
+                   }
+               } else {
+                   if (AiTrainUnit(table->Table[i], type)) {
+                       return 1;
+                   }
                }
            }
        }
     }
-
     return 0;
 }
 
@@ -1336,6 +1348,7 @@
     //  Collect resources.
     //
     AiCollectResources();
+
     //
     //  Check repair.
     //
Index: stratagus/src/ai/ai_rules.c
diff -u stratagus/src/ai/ai_rules.c:1.3 stratagus/src/ai/ai_rules.c:1.4
--- stratagus/src/ai/ai_rules.c:1.3     Sun Oct 26 10:34:59 2003
+++ stratagus/src/ai/ai_rules.c Fri Oct 31 04:14:46 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: ai_rules.c,v 1.3 2003/10/26 15:34:59 pludov Exp $
+//      $Id: ai_rules.c,v 1.4 2003/10/31 09:14:46 pludov Exp $
 
 //@{
 
@@ -585,19 +585,25 @@
 */
 global int AiEvaluateForceCost(int force, int total)
 {
-    int want, i;
+    int want, i, j;
 
     int count[UnitTypeMax + 1];
     int builders;
 
+    int equivtypesnb;
+    int equivtypes[UnitTypeMax + 1];
+    
     int globalCosts[MaxCosts];
     int globalTime;
     int cost, own;
-
+    
+    int forcesize;
+    
     AiUnitType *unittype;
-
+    UnitType * usedtype;
 
     AiForceCountUnits(force, count);
+
     // We have everything ready
     if (!total) {
        if (!AiForceSubstractWant(force, count)) {
@@ -613,37 +619,54 @@
 
     // For each "want" unittype, evaluate a cost, based on the number of units.
     unittype = AiPlayer->Force[force].UnitTypes;
+
+    forcesize=0;
+
     while (unittype) {
-       want = (-count[unittype->Type->Type]);
+       forcesize += unittype->Want;
+
+       want = (-count[UnitTypeEquivs[unittype->Type->Type]]);
 
-       // Don't count full unittypes...        
+       // Don't count full unittypes...
        if (want > 0) {
-           if (!CheckDependByIdent(AiPlayer->Player, unittype->Type->Ident)) {
-               return -1;
-           }
-           // Find number of units which can build this            
-           builders = AiCountUnitBuilders(unittype->Type);
+           // Never count it twice...
+           count[UnitTypeEquivs[unittype->Type->Type]] = 0;
 
+           // Find usable types for building
+           equivtypesnb = AiFindAvailableUnitTypeEquiv(unittype->Type, 
equivtypes);
+
+           // Find number of units which can build them
+           builders = 0;
+           usedtype = 0;
+           for (i = 0;i < equivtypesnb; i++) {
+               j = AiCountUnitBuilders(UnitTypes[equivtypes[i]]);
+               if (j > builders) {
+                   usedtype = UnitTypes[equivtypes[i]];
+                   builders = j;
+               }
+           }
+           
            // No way to build this, return -1
            if (!builders) {
                return -1;
            }
+
            // FIXME : all costs count the same there
            // ( sum all costs ... )
-
            for (i = 0; i < MaxCosts; i++) {
-               globalCosts[i] += want * unittype->Type->_Costs[i];
+               globalCosts[i] += want * usedtype->_Costs[i];
            }
 
            // FIXME : buildtime is assumed to be proportionnal to hitpoints 
 
            // Time to build the first
-           globalTime += unittype->Type->_HitPoints;
+           globalTime += usedtype->_HitPoints;
            // Time to build the nexts
-           globalTime += (unittype->Type->_HitPoints * want) / builders;
+           globalTime += (usedtype->_HitPoints * want) / builders;
        }
        unittype = unittype->Next;
     }
+
     // Count the ressource proportionnaly to player ressource 
     cost = 0;
 
@@ -661,10 +684,16 @@
     }
 
 
-    // FIXME : 20 / 1 ratio between buildtime and cost is hardcoded         
+    // FIXME : 20 / 1 ratio between buildtime and cost is hardcoded
     // Here globalTime is ~ the sum of all HitPoints...
     cost += globalTime / 20;
 
+    // Apply a multiplier on big forces :
+    // 100+(n-5)*10 % :  5 unit = 100 %, 15 units = 200 %, 25 units = 300 %, 
...  
+    if (forcesize > 5) {
+       cost = (cost * (100 + (forcesize - 5) * 10)) / 100;
+    }
+
     return cost;
 }
 
@@ -780,8 +809,8 @@
     AiEraseForce(AiScript->ownForce);
     AiPlayer->Force[AiScript->ownForce].Role =
        (defend ? AiForceRoleDefend : AiForceRoleAttack);
-    AiPlayer->Force[AiScript->ownForce].PopulateMode =
-       (defend ? AiForcePopulateAny : AiForcePopulateFromAttack);
+    AiPlayer->Force[AiScript->ownForce].PopulateMode = 
+       (defend ? AiForcePopulateAny : AiForcePopulateFromAttack);
     AiPlayer->Force[AiScript->ownForce].UnitsReusable = 0;
     AiPlayer->Force[AiScript->ownForce].HelpMode = AiForceHelpForce;
 
@@ -796,6 +825,7 @@
 
     // Compute force requirements.
     AiEvaluateScript(script->Action);
+
     // TODO : move from force 0 to force script->ownForce    
     // TODO : give some feedback on force 0 !
 
@@ -810,6 +840,7 @@
 global void AiFindDefendScript(int attackX, int attackY)
 {
     int bestValue;
+    int totalCost, leftCost;
     AiScriptAction *bestScriptAction;
 
     if (!AiPrepareScript(attackX, attackY, 12, 1)) {
@@ -825,8 +856,18 @@
        DebugLevel3Fn("no correct defense action script available...\n");
        return;
     }
-    DebugLevel3Fn("launch script with value %d\n" _C_ bestValue);
-    AiStartScript(bestScriptAction, "defend");
+
+    AiEvaluateScript(bestScriptAction->Action);
+
+    leftCost = AiEvaluateForceCost(AiScript->ownForce, 0);
+    totalCost = AiEvaluateForceCost(AiScript->ownForce, 1);
+    if (leftCost <= ((7 * totalCost) / 10)) {
+       DebugLevel3Fn("launch defense script\n");
+       AiStartScript(bestScriptAction, "defend");
+    }else{
+       DebugLevel3Fn("not ready for defense\n");
+       AiStartScript(bestScriptAction, "defend");
+    }
 }
 
 local Unit *RandomPlayerUnit(Player * player)
@@ -834,15 +875,31 @@
     int try;
     int unitId;
     Unit *unit;
+    AiActionEvaluation * action;
     if (!player->TotalNumUnits) {
        return NoUnitP;
     }
 
-    for (try = 0; try < 10; try++) {
+    for (try = 0; try < 20; try++) {
        unitId = SyncRand() % player->TotalNumUnits;
        unit = player->Units[unitId];
-       // FIXME : is this unit targettable ?   
-       if ((!unit->Removed) && (!((unit)->Orders[0].Action == UnitActionDie))) 
{
+
+       // FIXME : is this unit targettable ?
+       if ((unit->Removed) || ((unit)->Orders[0].Action == UnitActionDie)) {
+           continue;
+       }
+
+       // Don't take unit near past evaluations
+       action = AiPlayer->FirstEvaluation;
+       while (action) {
+           if ((abs(action->hotSpotX - unit->X) < 8)
+               && (abs(action->hotSpotY - unit->Y) < 8)) {
+               unit = NoUnitP;
+               break;
+           }
+           action = action->Next;
+       }
+       if (unit != NoUnitP) {
            return unit;
        }
     }
@@ -886,15 +943,42 @@
     return NoUnitP;
 }
 
+/**
+**     Remove the oldest action evaluation
+*/
 local void AiRemoveFirstAiPlayerEvaluation(void)
 {
     AiActionEvaluation *actionEvaluation = AiPlayer->FirstEvaluation;
 
     AiPlayer->FirstEvaluation = actionEvaluation->Next;
+    if (! AiPlayer->FirstEvaluation) {
+       AiPlayer->LastEvaluation = 0;
+    }
+
     free(actionEvaluation);
     AiPlayer->EvaluationCount--;
 }
 
+/**
+**     Remove outdated evaluations
+*/
+local void AiCleanAiPlayerEvaluations(void)
+{
+    int memorylimit;
+
+    // Don't keep more than AI_MEMORY_SIZE ( remove old ones )  
+    while (AiPlayer->EvaluationCount >= AI_MEMORY_SIZE) {
+       AiRemoveFirstAiPlayerEvaluation();
+    }
+
+    // Keep no more than 1 minutes.
+    memorylimit=GameCycle-30*60;
+
+    while (AiPlayer->FirstEvaluation && AiPlayer->FirstEvaluation->gamecycle < 
memorylimit){
+       AiRemoveFirstAiPlayerEvaluation();
+    }
+}
+
 global void AiPeriodicAttack(void)
 {
     AiScriptAction *bestScriptAction;
@@ -904,6 +988,9 @@
     AiActionEvaluation *bestActionEvaluation;
     int bestValue, bestHotSpot;
     int leftCost, totalCost;
+    int delta, bestDelta;
+
+    AiCleanAiPlayerEvaluations();
 
     // Find a random enemy unit.
     enemy = RandomEnemyUnit();
@@ -911,6 +998,7 @@
        DebugLevel3Fn("No enemy unit found for attack, giving up !\n");
        return;
     }
+
     // Find a unit as start point.
     // own=RandomPlayerUnit(AiPlayer->Player);
     // Need to set AiScript, to make AiEvaluateScript work
@@ -924,9 +1012,11 @@
        DebugLevel3Fn("No usable attack script, giving up !\n");
        return;
     }
+
     // Add a new ActionEvaluation at the end of the queue
     actionEvaluation = (AiActionEvaluation *) malloc(sizeof 
(AiActionEvaluation));
     actionEvaluation->aiScriptAction = bestScriptAction;
+    actionEvaluation->gamecycle = GameCycle;
     actionEvaluation->hotSpotX = enemy->X;
     actionEvaluation->hotSpotY = enemy->Y;
     actionEvaluation->value = bestScriptValue;
@@ -934,7 +1024,7 @@
        AiGetGaugeValue(ForceGauge(WATER_UNITS_VALUE, HOTSPOT_AREA, FOR_ENEMY))
        + AiGetGaugeValue(ForceGauge(GROUND_UNITS_VALUE, HOTSPOT_AREA, 
FOR_ENEMY))
        + AiGetGaugeValue(ForceGauge(AIR_UNITS_VALUE, HOTSPOT_AREA, FOR_ENEMY));
-    DebugLevel3Fn("new action at %d %d, hotspotValue=%d, cost=%d\n" _C_
+    DebugLevel2Fn("new action at %d %d, hotspotValue=%d, cost=%d\n" _C_
        enemy->X _C_ enemy->Y _C_
        actionEvaluation->hotSpotValue _C_ actionEvaluation->value);
 
@@ -948,11 +1038,6 @@
     }
     AiPlayer->LastEvaluation = actionEvaluation;
 
-    // Don't keep more than AI_MEMORY_SIZE ( remove old ones )  
-    while (AiPlayer->EvaluationCount > AI_MEMORY_SIZE) {
-       AiRemoveFirstAiPlayerEvaluation();
-    }
-
     // Iterate all actionEvalution. If one of them is better than all others, 
go !
     bestActionEvaluation = 0;
     bestValue = -1;
@@ -974,6 +1059,18 @@
        actionEvaluation = actionEvaluation->Next;
     }
 
+    if ((! bestActionEvaluation) && bestValue != -1 ){
+       // If nothing available, try the best compromis ( value - hotspot )
+       actionEvaluation = AiPlayer->FirstEvaluation;
+       bestDelta=0;
+       while (actionEvaluation) {
+           delta = (20 * actionEvaluation->hotSpotValue) / 
(actionEvaluation->value + 1);
+           if (bestDelta == -1 || delta <= bestDelta) {
+               bestActionEvaluation = actionEvaluation;
+           }
+       }
+    }
+
     if ((bestActionEvaluation)) {
        DebugLevel3Fn("has a best script, value=%d, hotspot=%d\n" _C_ bestValue 
_C_
            bestHotSpot);
@@ -985,15 +1082,20 @@
 
        leftCost = AiEvaluateForceCost(AiScript->ownForce, 0);
        totalCost = AiEvaluateForceCost(AiScript->ownForce, 1);
+       if (leftCost > totalCost) {
+           DebugLevel3Fn("Left cost superior to totalcost ( %d > %d )\n" _C_ 
leftCost _C_ totalCost);
+       }
 
-       if (leftCost <= ((8 * totalCost) / 10)) {
+       if (leftCost <= ((2 * totalCost) / 10)) {
            DebugLevel3Fn("Attack script !...\n");
            AiStartScript(bestActionEvaluation->aiScriptAction, "attack");
-       } else {
+       } else if (leftCost <= ((8 * totalCost) /10)) {
            DebugLevel3Fn("Not ready for attack script, wait...\n");
 
-           //AiForceTransfert(AiScript->ownForce,0);
            AiUpdateForce(1, AiScript->ownForce);
+           AiEraseForce(AiScript->ownForce);
+       } else {
+           DebugLevel3Fn("Attacking crisis ! reseting.\n");
            AiEraseForce(AiScript->ownForce);
        }
     }
Index: stratagus/src/ai/ccl_ai.c
diff -u stratagus/src/ai/ccl_ai.c:1.74 stratagus/src/ai/ccl_ai.c:1.75
--- stratagus/src/ai/ccl_ai.c:1.74      Wed Oct 29 18:11:55 2003
+++ stratagus/src/ai/ccl_ai.c   Fri Oct 31 04:14:46 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: ccl_ai.c,v 1.74 2003/10/29 23:11:55 pludov Exp $
+//      $Id: ccl_ai.c,v 1.75 2003/10/31 09:14:46 pludov Exp $
 
 //@{
 
@@ -73,6 +73,7 @@
     {
        {"`next",               NULL,           &((AiActionEvaluation *) 
0)->Next,      NULL},
        {"ai-script-action",    &IOAiScriptActionPtr,&((AiActionEvaluation *) 
0)->aiScriptAction,NULL},
+       {"gamecycle",           &IOInt,         &((AiActionEvaluation *) 
0)->gamecycle, NULL},
        {"hotspot-x",           &IOInt,         &((AiActionEvaluation *) 
0)->hotSpotX,  NULL},
        {"hotspot-y",           &IOInt,         &((AiActionEvaluation *) 
0)->hotSpotY,  NULL},
        {"hotspot-value",       &IOInt,         &((AiActionEvaluation *) 
0)->hotSpotValue,NULL},
@@ -693,6 +694,8 @@
                    AiHelperSetupTable(&AiHelpers.EquivCount, &AiHelpers.Equiv,
                        base->Type);
                    AiHelperInsert(AiHelpers.Equiv + base->Type, type);
+
+                   AiNewUnitTypeEquiv(base,type);
                    break;
                case 6:         // repair
                    AiHelperSetupTable(&AiHelpers.RepairCount, 
&AiHelpers.Repair,
@@ -817,7 +820,7 @@
 local void InsertUnitTypeRequests(UnitType * type, int count)
 {
     int n;
-
+    
     if (AiPlayer->UnitTypeRequests) {
        n = AiPlayer->UnitTypeRequestsCount;
        AiPlayer->UnitTypeRequests = realloc(AiPlayer->UnitTypeRequests,
@@ -1232,12 +1235,16 @@
        if (!count) {                   // Don't care
            continue;
        }
+
+       // Use the equivalent unittype.
+       type = UnitTypes[UnitTypeEquivs[type->Type]];
+
        //
        //      Look if already in force.
        //
        for (prev = &AiPlayer->Force[force].UnitTypes; (aiut = *prev);
            prev = &aiut->Next) {
-           if (aiut->Type == type) {   // found
+           if (UnitTypeEquivs[aiut->Type->Type] == type->Type) {       // found
                if (aiut->Want < count) {
                    aiut->Want = count;
                }
Index: stratagus/src/ai/new_ai.c
diff -u stratagus/src/ai/new_ai.c:1.81 stratagus/src/ai/new_ai.c:1.82
--- stratagus/src/ai/new_ai.c:1.81      Wed Oct 29 18:11:55 2003
+++ stratagus/src/ai/new_ai.c   Fri Oct 31 04:14:46 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: new_ai.c,v 1.81 2003/10/29 23:11:55 pludov Exp $
+//      $Id: new_ai.c,v 1.82 2003/10/31 09:14:46 pludov Exp $
 
 
 //@{
@@ -57,6 +57,11 @@
 **
 **     Manage the inititialse and cleanup of the AI players.
 **
+**     ::InitAiModule(void)
+**
+**             Initialise all global varaibles and structures.
+**             Called before AiInit, or before game loading.
+**
 **     ::AiInit(::Player)
 **
 **             Called for each player, to setup the AI structures
@@ -176,44 +181,55 @@
 
 local void debugForces(void)
 {
-    const AiUnit *aiunit;
-    const AiUnitType *aiunittype;
+    const AiActionEvaluation * aiaction;
     int force, i;
-    int count[UnitTypeMax];
-
-    DebugLevel3Fn(" ! : completed    A/D : attacking/defending\n");
+    int count[UnitTypeMax+1];
+    int want[UnitTypeMax+1];
+    char * str;
+
+    DebugLevel2Fn(" AI MEMORY (%d)\n" _C_ AiPlayer->EvaluationCount);
+    aiaction = AiPlayer->FirstEvaluation;
+    while (aiaction) {
+       str = 
gh_scm2newstr(gh_car(gh_car(aiaction->aiScriptAction->Action)),NULL);
+       DebugLevel2(" %8d: (%3d,%3d) => points:%9d, needs: %9d ( %s )\n" _C_
+           aiaction->gamecycle _C_
+           aiaction->hotSpotX _C_
+           aiaction->hotSpotY _C_
+           aiaction->hotSpotValue _C_
+           aiaction->value _C_
+           str);
+       free(str);
+       aiaction = aiaction->Next;
+    }
+    DebugLevel2Fn(" AI FORCES      ! : completed    A/D : 
attacking/defending\n");
     for (force = 0; force < AI_MAX_FORCES; force++) {
-       DebugLevel3Fn("force %5d %c%c :" _C_
+       DebugLevel2("force %5d %c%c :" _C_
            force _C_
            (AiPlayer->Force[force].Role == AiForceRoleAttack ? 'A' : 'D') _C_
            (AiPlayer->Force[force].Completed ? '!' : ' '));
 
-       for (i = 0; i < UnitTypeMax; i++) {
-           count[i] = 0;
+       AiForceCountUnits(force, count);
+       
+       for (i = 0; i <= UnitTypeMax; i++) {
+           want[i] = 0;
        }
-
-       aiunit = AiPlayer->Force[force].Units;
-
-       while (aiunit) {
-           count[aiunit->Unit->Type->Type]++;
-           aiunit = aiunit->Next;
-       }
-
-       aiunittype = AiPlayer->Force[force].UnitTypes;
-       while (aiunittype) {
-           DebugLevel3Fn(" %s(%d/%d)" _C_ aiunittype->Type->
-               Ident _C_ count[aiunittype->Type->Type] _C_ aiunittype->Want);
-           count[aiunittype->Type->Type] = 0;
-           aiunittype = aiunittype->Next;
-       }
-
+       AiForceSubstractWant(force, want);
+       
        for (i = 0; i < UnitTypeMax; i++) {
-           if (count[i]) {
-               DebugLevel3Fn(" %s(%d/0)" _C_ UnitTypes[i]->Ident _C_ count[i]);
+           if (count[i] || want[i]) {
+               DebugLevel2(" %s(%d/%d)" _C_ UnitTypes[i]->Ident _C_ count[i] 
_C_ want[i]);
            }
        }
 
-       DebugLevel3Fn("\n");
+       if (force > AI_GENERIC_FORCES || force == 0) {
+           if (!gh_null_p(AiPlayer->Scripts[force ? force - AI_GENERIC_FORCES 
: 0].Script)) {
+               DebugLevel2(" => ");
+               fflush(stdout);
+               gh_display(gh_car(AiPlayer->Scripts[force ? force - 
AI_GENERIC_FORCES : 0].Script));
+               CclFlushOutput();
+           }
+       }
+       DebugLevel2("\n");
     }
 }
 
@@ -227,20 +243,22 @@
     SCM value;
 
     pai = AiPlayer;
+
+    // Debugging
     debugForces();
+
     for (i = 0; i < AI_MAX_RUNNING_SCRIPTS; i++) {
        AiScript = pai->Scripts + i;
        if (!gh_null_p(AiScript->Script)) {
-           /*
-              if( pai->ScriptDebug ) {         // display executed command
-              DebugLevel3Fn("%d.%d (%12s) @ %3d.%3d :" _C_ pai->Player->Player 
_C_ i _C_ AiScript->ident _C_ AiScript->HotSpot_X _C_ AiScript->HotSpot_Y);
-              gh_display(AiScript->Script);
-              gh_newline();
-              } */
+           /*DebugLevel3Fn("%d.%d (%12s) @ %3d.%3d :" _C_ pai->Player->Player 
_C_ i _C_ AiScript->ident _C_ AiScript->HotSpot_X _C_ AiScript->HotSpot_Y);
+           gh_display(AiScript->Script);
+           gh_newline();*/
+
            value = gh_eval(gh_car(AiScript->Script), NIL);
            if (!gh_eq_p(value, SCM_BOOL_T)) {
                AiScript->Script = gh_cdr(AiScript->Script);
            }
+
            if ((gh_null_p(AiScript->Script)) && (AiScript->ownForce)) {
                AiEraseForce(AiScript->ownForce);
            }
@@ -744,7 +762,7 @@
 {
     CLprintf(file, "\n;;; -----------------------------------------\n");
     CLprintf(file,
-       ";;; MODULE: AI $Id: new_ai.c,v 1.81 2003/10/29 23:11:55 pludov Exp 
$\n\n");
+       ";;; MODULE: AI $Id: new_ai.c,v 1.82 2003/10/31 09:14:46 pludov Exp 
$\n\n");
 
     SaveAiTypesWcName(file);
     SaveAiHelper(file);
@@ -865,6 +883,14 @@
 }
 
 /**
+**     Initialise global structures of the AI
+*/
+global void InitAiModule(void)
+{
+    AiResetUnitTypeEquiv();
+}
+
+/**
 **     Cleanup the AI.
 */
 global void CleanAi(void)
@@ -996,6 +1022,9 @@
        free(AiTypeWcNames);
        AiTypeWcNames = NULL;
     }
+
+    AiResetUnitTypeEquiv();
+    
     // TODO : AiScriptActions are not freed
     AiScriptActionNum = 0;
 }
@@ -1042,19 +1071,20 @@
 local void AiRemoveFromBuilded(PlayerAi * pai, const UnitType * type)
 {
     int i;
+    int equivalents[UnitTypeMax+1];
+    int equivalentsCount;
 
     if (AiRemoveFromBuilded2(pai, type)) {
        return;
     }
+
     //
     //  This could happen if an upgrade is ready, look for equivalent units.
     //
-    if (type->Type < AiHelpers.EquivCount && AiHelpers.Equiv[type->Type]) {
-       DebugLevel2Fn("Equivalence for %s\n" _C_ type->Ident);
-       for (i = 0; i < AiHelpers.Equiv[type->Type]->Count; ++i) {
-           if (AiRemoveFromBuilded2(pai, 
AiHelpers.Equiv[type->Type]->Table[i])) {
-               return;
-           }
+    equivalentsCount = AiFindUnitTypeEquiv(type, equivalents);
+    for (i = 0; i < equivalentsCount; i++) {
+       if (AiRemoveFromBuilded2(pai, UnitTypes[equivalents[i]])) {
+           return;
        }
     }
 
@@ -1063,6 +1093,7 @@
            ("My guess is that you built something under ai me. naughty 
boy!\n");
        return;
     }
+
     DebugCheck(1);
 }
 
Index: stratagus/src/clone/ccl.c
diff -u stratagus/src/clone/ccl.c:1.121 stratagus/src/clone/ccl.c:1.122
--- stratagus/src/clone/ccl.c:1.121     Wed Oct 29 07:58:36 2003
+++ stratagus/src/clone/ccl.c   Fri Oct 31 04:14:46 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: ccl.c,v 1.121 2003/10/29 12:58:36 mr-russ Exp $
+//     $Id: ccl.c,v 1.122 2003/10/31 09:14:46 pludov Exp $
 
 //@{
 
@@ -68,6 +68,7 @@
 #include "cdaudio.h"
 #include "spells.h"
 
+
 /*----------------------------------------------------------------------------
 --     Variables
 ----------------------------------------------------------------------------*/
@@ -247,6 +248,15 @@
 #endif
 }
 
+global void CclFlushOutput(void)
+{
+#ifdef USE_GUILE
+    scm_flush_all_ports();
+#else
+    fflush(stdout);
+#endif
+}
+
 /*............................................................................
 ..     Config
 ............................................................................*/
@@ -1046,7 +1056,7 @@
     }
 
     fprintf(fd, ";;; -----------------------------------------\n");
-    fprintf(fd, ";;; $Id: ccl.c,v 1.121 2003/10/29 12:58:36 mr-russ Exp $\n");
+    fprintf(fd, ";;; $Id: ccl.c,v 1.122 2003/10/31 09:14:46 pludov Exp $\n");
 
     fprintf(fd, "(set-video-resolution! %d %d)\n", VideoWidth, VideoHeight);
     
@@ -1071,7 +1081,7 @@
     }
 
     fprintf(fd, ";;; -----------------------------------------\n");
-    fprintf(fd, ";;; $Id: ccl.c,v 1.121 2003/10/29 12:58:36 mr-russ Exp $\n");
+    fprintf(fd, ";;; $Id: ccl.c,v 1.122 2003/10/31 09:14:46 pludov Exp $\n");
 
     // Global options
     if (OriginalFogOfWar) {
@@ -1182,7 +1192,7 @@
     extern SCM oblistvar;
 
     CLprintf(file, "\n;;; -----------------------------------------\n");
-    CLprintf(file, ";;; MODULE: CCL $Id: ccl.c,v 1.121 2003/10/29 12:58:36 
mr-russ Exp $\n\n");
+    CLprintf(file, ";;; MODULE: CCL $Id: ccl.c,v 1.122 2003/10/31 09:14:46 
pludov Exp $\n\n");
 
     for (list = oblistvar; gh_list_p(list); list = gh_cdr(list)) {
        SCM sym;
Index: stratagus/src/clone/clone.c
diff -u stratagus/src/clone/clone.c:1.216 stratagus/src/clone/clone.c:1.217
--- stratagus/src/clone/clone.c:1.216   Tue Oct 28 12:03:40 2003
+++ stratagus/src/clone/clone.c Fri Oct 31 04:14:47 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: clone.c,v 1.216 2003/10/28 17:03:40 jsalmon3 Exp $
+//     $Id: clone.c,v 1.217 2003/10/31 09:14:47 pludov Exp $
 
 //@{
 
@@ -1516,7 +1516,12 @@
        --argc;
     }
 
+
     InitCcl();                         // init CCL and load configurations!
+
+    // Initialise AI module
+    InitAiModule();
+
     LoadCcl();
 
     main1(argc, argv);
Index: stratagus/src/game/loadgame.c
diff -u stratagus/src/game/loadgame.c:1.65 stratagus/src/game/loadgame.c:1.66
--- stratagus/src/game/loadgame.c:1.65  Fri Oct  3 06:37:08 2003
+++ stratagus/src/game/loadgame.c       Fri Oct 31 04:14:47 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: loadgame.c,v 1.65 2003/10/03 10:37:08 n0body Exp $
+//     $Id: loadgame.c,v 1.66 2003/10/31 09:14:47 pludov Exp $
 
 //@{
 
@@ -152,6 +152,9 @@
     InitDependencies();
 
     InitButtons();
+
+    InitAiModule();
+
 #ifdef HIERARCHIC_PATHFINDER
     PfHierInitialize();
 #endif
Index: stratagus/src/include/ai.h
diff -u stratagus/src/include/ai.h:1.29 stratagus/src/include/ai.h:1.30
--- stratagus/src/include/ai.h:1.29     Sun Aug 17 11:57:07 2003
+++ stratagus/src/include/ai.h  Fri Oct 31 04:14:47 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: ai.h,v 1.29 2003/08/17 15:57:07 n0body Exp $
+//     $Id: ai.h,v 1.30 2003/10/31 09:14:47 pludov Exp $
 
 #ifndef __AI_H__
 #define __AI_H__
@@ -54,11 +54,12 @@
 extern void AiEachCycle(Player* player);       /// Called each game cycle
 extern void AiEachSecond(Player* player);      /// Called each second
 
+extern void InitAiModule(void);                        /// Init AI global 
structures
 extern void AiInit(Player* player);            /// Init AI for this player
 extern void CleanAi(void);                     /// Cleanup the AI module
 extern void SaveAi(CLFile*file);               /// Save the AI state
 
-extern void AiCclRegister(void);       /// Register ccl features
+extern void AiCclRegister(void);               /// Register ccl features
 
 /*--------------------------------------------------------
 --     Call Backs/Triggers
Index: stratagus/src/include/ccl.h
diff -u stratagus/src/include/ccl.h:1.39 stratagus/src/include/ccl.h:1.40
--- stratagus/src/include/ccl.h:1.39    Mon Oct 27 05:49:37 2003
+++ stratagus/src/include/ccl.h Fri Oct 31 04:14:48 2003
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: ccl.h,v 1.39 2003/10/27 10:49:37 pludov Exp $
+//     $Id: ccl.h,v 1.40 2003/10/31 09:14:48 pludov Exp $
 
 #ifndef __CCL_H__
 #define __CCL_H__
@@ -172,6 +172,7 @@
 
 extern void CclGcProtect(SCM obj);     /// Protect scm object for GC
 extern void CclGcUnprotect(SCM obj);   /// Unprotect scm object for GC
+extern void CclFlushOutput();          /// Flush ccl output
 extern void InitCcl(void);             /// Initialise ccl
 extern void LoadCcl(void);             /// Load ccl config file
 extern void SaveCcl(CLFile* file);     /// Save CCL module




reply via email to

[Prev in Thread] Current Thread [Next in Thread]