hedgewars/uAI.pas
changeset 191 a03c2d037e24
parent 183 57c2ef19f719
child 193 56885ea29202
--- a/hedgewars/uAI.pas	Thu Oct 05 20:13:51 2006 +0000
+++ b/hedgewars/uAI.pas	Sun Oct 08 18:17:52 2006 +0000
@@ -19,27 +19,21 @@
 unit uAI;
 interface
 {$INCLUDE options.inc}
-procedure ProcessBot;
+procedure ProcessBot(FrameNo: Longword);
 procedure FreeActionsList;
 
 implementation
-uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc;
+uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc,
+     uAIThinkStack, uConsole;
 
 var BestActions: TActions;
-    ThinkThread: PSDL_Thread = nil;
-    StopThinking: boolean;
     CanUseAmmo: array [TAmmoType] of boolean;
+    AIThinkStart: Longword;
+    isThinking: boolean = false;
 
 procedure FreeActionsList;
 begin
-{$IFDEF DEBUGFILE}AddFileLog('FreeActionsList called');{$ENDIF}
-if ThinkThread <> nil then
-   begin
-   {$IFDEF DEBUGFILE}AddFileLog('Waiting AI thread to finish');{$ENDIF}
-   StopThinking:= true;
-   SDL_WaitThread(ThinkThread, nil);
-   ThinkThread:= nil
-   end;
+isThinking:= false;
 BestActions.Count:= 0;
 BestActions.Pos:= 0
 end;
@@ -92,206 +86,160 @@
            end;
         if a = High(TAmmoType) then a:= Low(TAmmoType)
                                else inc(a)
-       until (a = aa) or (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0)
+       until (a = aa) or (PHedgehog(Me.Hedgehog).AttacksNum > 0)
        end
 end;
 
 procedure Walk(Me: PGear);
 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;
-    begin
-    Result:= (Stack.Count < cBranchStackSize) and (Actions.Count < MAXACTIONS - 5);
-    if Result then
-       with Stack.States[Stack.Count] do
-            begin
-            WastedTicks:= Ticks;
-            MadeActions:= Actions;
-            Hedgehog:= Me;
-            Hedgehog.Message:= Dir;
-            inc(Stack.Count)
-            end
-    end;
-
-    procedure Pop(out Ticks: Longword; out Actions: TActions; out Me: TGear);
-    begin
-    dec(Stack.Count);
-    with Stack.States[Stack.Count] do
-         begin
-         Ticks:= WastedTicks;
-         Actions:= MadeActions;
-         Me:= Hedgehog
-         end
-    end;
-
-    function PosInThinkStack(Me: PGear): boolean;
-    var i: Longword;
-    begin
-    i:= 0;
-    Result:= false;
-    while (i < Stack.Count) and not Result do
-          begin
-          Result:= (abs(Stack.States[i].Hedgehog.X - Me.X) +
-                    abs(Stack.States[i].Hedgehog.Y - Me.Y) <= 2)
-                    and (Stack.States[i].Hedgehog.Message = Me.Message);
-          inc(i)
-          end
-    end;
-
-
 var Actions: TActions;
-    ticks, maxticks, steps, BotLevel, tmp: Longword;
-    BaseRate, BestRate, Rate: integer;
+    ticks, maxticks, steps, BotLevel: Longword;
+    BaseRate, Rate: integer;
     GoInfo: TGoInfo;
     CanGo: boolean;
     AltMe: TGear;
 begin
-Actions.Count:= 0;
-Actions.Pos:= 0;
-Actions.Score:= 0;
-Stack.Count:= 0;
 BotLevel:= PHedgehog(Me.Hedgehog).BotLevel;
 
-tmp:= random(2) + 1;
-Push(0, Actions, Me^, tmp);
-Push(0, Actions, Me^, tmp xor 3);
-
 if (Me.State and gstAttacked) = 0 then maxticks:= max(0, TurnTimeLeft - 5000 - 4000 * BotLevel)
                                   else maxticks:= TurnTimeLeft;
 
-if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me);
-BestRate:= RatePlace(Me);
-BaseRate:= max(BestRate, 0);
+
+BaseRate:= max(RatePlace(Me), 0);
 
-while (Stack.Count > 0) and not StopThinking do
-    begin
-    Pop(ticks, Actions, Me^);
-
+repeat
+    if not Pop(ticks, Actions, Me^) then
+       begin
+       isThinking:= false;
+       exit
+       end;
     AddAction(Actions, Me.Message, aim_push, 250);
     AddAction(Actions, aia_WaitX, round(Me.X), 0);
     AddAction(Actions, Me.Message, aim_release, 0);
     steps:= 0;
 
-    while (not StopThinking) and (not PosInThinkStack(Me)) do
+    while not PosInThinkStack(Me) do
        begin
+       if SDL_GetTicks - AIThinkStart > 3 then
+          begin
+          writetoconsole(inttostr(SDL_GetTicks - AIThinkStart) + ' ');
+          dec(Actions.Count, 3);
+          Push(ticks, Actions, Me^, Me^.Message);
+          exit
+          end;
+          
        CanGo:= HHGo(Me, @AltMe, GoInfo);
        inc(ticks, GoInfo.Ticks);
        if ticks > maxticks then break;
        
        if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support
           if Push(ticks, Actions, AltMe, Me^.Message) then
-             with Stack.States[Pred(Stack.Count)] do
+             with ThinkStack.States[Pred(ThinkStack.Count)] do
                   begin
                   AddAction(MadeActions, aia_HJump, 0, 305);
                   AddAction(MadeActions, aia_HJump, 0, 350);
                   end;
        if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support
           if Push(ticks, Actions, AltMe, Me^.Message) then
-             with Stack.States[Pred(Stack.Count)] do
+             with ThinkStack.States[Pred(ThinkStack.Count)] do
                   AddAction(MadeActions, aia_LJump, 0, 305);
 
        if not CanGo then break;
        inc(steps);
        Actions.actions[Actions.Count - 2].Param:= round(Me.X);
        Rate:= RatePlace(Me);
-       if Rate > BestRate then
+       if Rate > BaseRate then
           begin
           BestActions:= Actions;
-          BestRate:= Rate;
-          Me.State:= Me.State or gstAttacked // we have better place, go there and don't use ammo
+          BestActions.Score:= 1;
+          isThinking:= false;
+          exit
           end
-       else if Rate < BestRate then break;
+       else if Rate < BaseRate then break;
        if ((Me.State and gstAttacked) = 0)
            and ((steps mod 4) = 0) then TestAmmos(Actions, Me);
        if GoInfo.FallPix >= FallPixForBranching then
           Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
        end;
-
-    if BestRate > BaseRate then exit
-    end
+until false
 end;
 
-procedure Think(Me: PGear); cdecl;
+procedure Think(Me: PGear);
 var BackMe, WalkMe: TGear;
-    StartTicks: Longword;
+//    StartTicks: Longword;
 begin
-StartTicks:= GameTicks;
-BestActions.Count:= 0;
-BestActions.Pos:= 0;
-BestActions.Score:= Low(integer);
+AIThinkStart:= SDL_GetTicks;
 BackMe:= Me^;
 WalkMe:= BackMe;
 if (Me.State and gstAttacked) = 0 then
    if Targets.Count > 0 then
       begin
       Walk(@WalkMe);
-      if (StartTicks > GameTicks - 1500) and not StopThinking then SDL_Delay(2000);
-      if BestActions.Score < -1023 then
+      if not isThinking then
          begin
-         BestActions.Count:= 0;
-         AddAction(BestActions, aia_Skip, 0, 250);
-         end;
+         if BestActions.Score < -1023 then
+            begin
+            BestActions.Count:= 0;
+            AddAction(BestActions, aia_Skip, 0, 250);
+            end;
+         Me.State:= Me.State and not gstHHThinking
+         end
       end else
 else begin
-      Walk(@WalkMe);
-      while (not StopThinking) and (BestActions.Count = 0) do
-            begin
-            SDL_Delay(100);
-            FillBonuses(true);
-            WalkMe:= BackMe;
-            Walk(@WalkMe)
-            end
-      end;
-Me.State:= Me.State and not gstHHThinking
+      FillBonuses(true);
+      Walk(@WalkMe)
+      end
 end;
 
 procedure StartThink(Me: PGear);
 var a: TAmmoType;
+    tmp: integer;
 begin
 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit;
+ThinkingHH:= Me;
+isThinking:= true;
+
+ClearThinkStack;
+
 Me.State:= Me.State or gstHHThinking;
 Me.Message:= 0;
-StopThinking:= false;
-ThinkingHH:= Me;
 FillTargets;
 if Targets.Count = 0 then
    begin
    OutError('AI: no targets!?');
    exit
    end;
+
 FillBonuses((Me.State and gstAttacked) <> 0);
+
 for a:= Low(TAmmoType) to High(TAmmoType) do
     CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me.Hedgehog), a);
-{$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF}
-ThinkThread:= SDL_CreateThread(@Think, Me)
+
+BestActions.Count:= 0;
+BestActions.Pos:= 0;
+BestActions.Score:= 0;
+tmp:= random(2) + 1;
+Push(0, BestActions, Me^, tmp);
+Push(0, BestActions, Me^, tmp xor 3);
+BestActions.Score:= Low(integer);
+
+Think(Me)
 end;
 
-procedure ProcessBot;
-const StartTicks: Longword = 0;
+procedure ProcessBot(FrameNo: Longword);
+const LastFrameNo: Longword = 0;
 begin
+if FrameNo = LastFrameNo then exit;
+LastFrameNo:= FrameNo;
 with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
      if (Gear <> nil)
         and ((Gear.State and gstHHDriven) <> 0)
         and (TurnTimeLeft < cHedgehogTurnTime - 50) then
-        if ((Gear.State and gstHHThinking) = 0) then
-           if (BestActions.Pos >= BestActions.Count) then
-              begin
-              StartThink(Gear);
-              StartTicks:= GameTicks
-              end else ProcessAction(BestActions, Gear)
-        else if (GameTicks - StartTicks) > cMaxAIThinkTime then StopThinking:= true
+        if not isThinking then
+           if (BestActions.Pos >= BestActions.Count) then StartThink(Gear)
+                                                     else ProcessAction(BestActions, Gear)
+        else Think(Gear)
 end;
 
 end.