hedgewars/uAI.pas
branch0.9.17
changeset 6400 a057306acea6
parent 6395 bb04d7a9f7e2
child 6415 af2047bb4f70
--- a/hedgewars/uAI.pas	Mon Nov 14 13:31:38 2011 -0500
+++ b/hedgewars/uAI.pas	Sat Nov 19 14:30:58 2011 -0500
@@ -60,6 +60,49 @@
 BestActions.Pos:= 0
 end;
 
+
+
+const cBranchStackSize = 12;
+type TStackEntry = record
+                   WastedTicks: Longword;
+                   MadeActions: TActions;
+                   Hedgehog: TGear;
+                   end;
+
+var Stack: record
+           Count: Longword;
+           States: array[0..Pred(cBranchStackSize)] of TStackEntry;
+           end;
+
+function Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer): boolean;
+var bRes: boolean;
+begin
+    bRes:= (Stack.Count < cBranchStackSize) and (Actions.Count < MAXACTIONS - 5);
+    if bRes then
+        with Stack.States[Stack.Count] do
+            begin
+            WastedTicks:= Ticks;
+            MadeActions:= Actions;
+            Hedgehog:= Me;
+            Hedgehog.Message:= Dir;
+            inc(Stack.Count)
+            end;
+    Push:= bRes
+end;
+
+procedure Pop(var Ticks: Longword; var Actions: TActions; var Me: TGear);
+begin
+    dec(Stack.Count);
+    with Stack.States[Stack.Count] do
+        begin
+        Ticks:= WastedTicks;
+        Actions:= MadeActions;
+        Me:= Hedgehog
+        end
+end;
+
+
+
 procedure TestAmmos(var Actions: TActions; Me: PGear; isMoved: boolean);
 var BotLevel: Byte;
     ap: TAttackParams;
@@ -89,6 +132,7 @@
               begin
               BestActions:= Actions;
               inc(BestActions.Score, Score);
+              BestActions.isWalkingToABetterPlace:= false;
 
               if (ap.Angle > 0) then AddAction(BestActions, aia_LookRight, 0, 200, 0, 0)
               else if (ap.Angle < 0) then AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0);
@@ -129,61 +173,23 @@
        end
 end;
 
-procedure Walk(Me: PGear);
+procedure Walk(Me: PGear; var Actions: TActions);
 const FallPixForBranching = cHHRadius * 2 + 8;
-      cBranchStackSize = 12;
-
-type TStackEntry = record
-                   WastedTicks: Longword;
-                   MadeActions: TActions;
-                   Hedgehog: TGear;
-                   end;
-
-var Stack: record
-           Count: Longword;
-           States: array[0..Pred(cBranchStackSize)] of TStackEntry;
-           end;
-
-    function Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer): boolean;
-    var bRes: boolean;
-    begin
-    bRes:= (Stack.Count < cBranchStackSize) and (Actions.Count < MAXACTIONS - 5);
-    if bRes then
-       with Stack.States[Stack.Count] do
-            begin
-            WastedTicks:= Ticks;
-            MadeActions:= Actions;
-            Hedgehog:= Me;
-            Hedgehog.Message:= Dir;
-            inc(Stack.Count)
-            end;
-    Push:= bRes
-    end;
-
-    procedure Pop(var Ticks: Longword; var Actions: TActions; var Me: TGear);
-    begin
-    dec(Stack.Count);
-    with Stack.States[Stack.Count] do
-         begin
-         Ticks:= WastedTicks;
-         Actions:= MadeActions;
-         Me:= Hedgehog
-         end
-    end;
-
-var Actions: TActions;
+var
     ticks, maxticks, steps, tmp: Longword;
     BaseRate, BestRate, Rate: integer;
     GoInfo: TGoInfo;
     CanGo: boolean;
     AltMe: TGear;
     BotLevel: Byte;
+    a: TAmmoType;
 begin
 ticks:= 0; // avoid compiler hint
-Actions.Count:= 0;
-Actions.Pos:= 0;
-Actions.Score:= 0;
 Stack.Count:= 0;
+
+for a:= Low(TAmmoType) to High(TAmmoType) do
+    CanUseAmmo[a]:= Assigned(AmmoTests[a].proc) and HHHasAmmo(Me^.Hedgehog^, a);
+
 BotLevel:= Me^.Hedgehog^.BotLevel;
 
 tmp:= random(2) + 1;
@@ -240,6 +246,7 @@
        if Rate > BestRate then
           begin
           BestActions:= Actions;
+          BestActions.isWalkingToABetterPlace:= true;
           BestRate:= Rate;
           Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
           end
@@ -256,40 +263,84 @@
 
 function Think(Me: Pointer): ptrint;
 var BackMe, WalkMe: TGear;
-    StartTicks: Longword;
+    StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i: Longword;
+    switchImmediatelyAvailable, switchAvailable: boolean;
+    Actions: TActions;
 begin
 InterlockedIncrement(hasThread);
 StartTicks:= GameTicks;
-BackMe:= PGear(Me)^;
+currHedgehogIndex:= CurrentTeam^.CurrHedgehog;
+itHedgehog:= currHedgehogIndex;
+switchesNum:= 0;
+
+switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher);
+switchAvailable:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch);
 
 if (PGear(Me)^.State and gstAttacked) = 0 then
    if Targets.Count > 0 then
       begin
-      WalkMe:= BackMe;
-      Walk(@WalkMe);
-      if (StartTicks > GameTicks - 1500) and (not StopThinking) then SDL_Delay(1000);
-      if BestActions.Score < -1023 then
-         begin
-         BestActions.Count:= 0;
-         AddAction(BestActions, aia_Skip, 0, 250, 0, 0);
-         end;
+        // iterate over current team hedgehogs
+        repeat
+            WalkMe:= CurrentTeam^.Hedgehogs[itHedgehog].Gear^;
+
+            Actions.Count:= 0;
+            Actions.Pos:= 0;
+            Actions.Score:= 0;
+            if switchesNum > 0 then
+                begin
+                if not switchImmediatelyAvailable then
+                    begin
+                    // when AI has to use switcher, make it cost smth
+                    Actions.Score:= -20000;
+                    AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0);                    
+                    AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0);
+                    AddAction(Actions, aia_attack, aim_release, 1, 0, 0);
+                    end;
+                for i:= 1 to switchesNum do
+                    AddAction(Actions, aia_Switch, 0, 300 + random(200), 0, 0);
+                end;
+            Walk(@WalkMe, Actions);
+
+            // find another hog in team
+            repeat
+                itHedgehog:= Succ(itHedgehog) mod CurrentTeam^.HedgehogsNumber;
+            until (itHedgehog = currHedgehogIndex) or (CurrentTeam^.Hedgehogs[itHedgehog].Gear <> nil);
+
+            inc(switchesNum);
+        until (not (switchImmediatelyAvailable or switchAvailable))
+            or StopThinking 
+            or (itHedgehog = currHedgehogIndex)
+            or BestActions.isWalkingToABetterPlace;
+
+        if (StartTicks > GameTicks - 1500) and (not StopThinking) then SDL_Delay(1000);
+
+        if (BestActions.Score < -1023) and (not BestActions.isWalkingToABetterPlace) then
+            begin
+            BestActions.Count:= 0;
+            AddAction(BestActions, aia_Skip, 0, 250, 0, 0);
+            end;
+
       end else
 else begin
-      while (not StopThinking) and (BestActions.Count = 0) do
-            begin
-            FillBonuses(true);
-            WalkMe:= BackMe;
-            Walk(@WalkMe);
-            if not StopThinking then SDL_Delay(100)
-            end
-      end;
+    BackMe:= PGear(Me)^;
+    while (not StopThinking) and (BestActions.Count = 0) do
+        begin
+        FillBonuses(true);
+        WalkMe:= BackMe;
+        Actions.Count:= 0;
+        Actions.Pos:= 0;
+        Actions.Score:= 0;
+        Walk(@WalkMe, Actions);
+        if not StopThinking then SDL_Delay(100)
+        end
+    end;
+
 PGear(Me)^.State:= PGear(Me)^.State and not gstHHThinking;
 Think:= 0;
 InterlockedDecrement(hasThread)
 end;
 
 procedure StartThink(Me: PGear);
-var a: TAmmoType;
 begin
 if ((Me^.State and (gstAttacking or gstHHJumping or gstMoving)) <> 0)
    or isInMultiShoot then exit;
@@ -301,6 +352,7 @@
 BestActions.Count:= 0;
 BestActions.Pos:= 0;
 BestActions.Score:= Low(LongInt);
+BestActions.isWalkingToABetterPlace:= false;
 
 StopThinking:= false;
 ThinkingHH:= Me;
@@ -313,8 +365,6 @@
    end;
 
 FillBonuses((Me^.State and gstAttacked) <> 0);
-for a:= Low(TAmmoType) to High(TAmmoType) do
-    CanUseAmmo[a]:= Assigned(AmmoTests[a].proc) and HHHasAmmo(Me^.Hedgehog^, a);
 AddFileLog('Enter Think Thread');
 BeginThread(@Think, Me, ThinkThread)
 end;