hedgewars/uAI.pas
changeset 80 3c3dc6a148ca
parent 75 d2b737858ff7
child 82 2f4f3236cccc
equal deleted inserted replaced
79:29b477319854 80:3c3dc6a148ca
    62     Angle, Power, Score, ExplX, ExplY, ExplR: integer;
    62     Angle, Power, Score, ExplX, ExplY, ExplR: integer;
    63     i: integer;
    63     i: integer;
    64     a, aa: TAmmoType;
    64     a, aa: TAmmoType;
    65 begin
    65 begin
    66 for i:= 0 to Pred(Targets.Count) do
    66 for i:= 0 to Pred(Targets.Count) do
    67     if Targets.ar[i].Score >= 0 then
    67     if (Targets.ar[i].Score >= 0) then
    68        begin
    68        begin
    69        with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
    69        with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
    70             a:= Ammo[CurSlot, CurAmmo].AmmoType;
    70             a:= Ammo[CurSlot, CurAmmo].AmmoType;
    71        aa:= a;
    71        aa:= a;
    72        repeat
    72        repeat
   102        until (a = aa) or (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0)
   102        until (a = aa) or (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0)
   103        end
   103        end
   104 end;
   104 end;
   105 
   105 
   106 procedure Walk(Me: PGear);
   106 procedure Walk(Me: PGear);
   107 const FallTicksForBranching = cHHRadius * 2 + 8;
   107 const FallPixForBranching = cHHRadius * 2 + 8;
   108       cBranchStackSize = 8;
   108       cBranchStackSize = 12;
   109       
   109       
   110 type TStackEntry = record
   110 type TStackEntry = record
   111                    WastedTicks: Longword;
   111                    WastedTicks: Longword;
   112                    MadeActions: TActions;
   112                    MadeActions: TActions;
   113                    Hedgehog: TGear;
   113                    Hedgehog: TGear;
   116 var Stack: record
   116 var Stack: record
   117            Count: Longword;
   117            Count: Longword;
   118            States: array[0..Pred(cBranchStackSize)] of TStackEntry;
   118            States: array[0..Pred(cBranchStackSize)] of TStackEntry;
   119            end;
   119            end;
   120 
   120 
   121     procedure Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer);
   121     function Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer): boolean;
   122     begin
   122     begin
   123     if Stack.Count < cBranchStackSize then
   123     Result:= (Stack.Count < cBranchStackSize) and (Actions.Count < MAXACTIONS - 5);
       
   124     if Result then
   124        with Stack.States[Stack.Count] do
   125        with Stack.States[Stack.Count] do
   125             begin
   126             begin
   126             WastedTicks:= Ticks;
   127             WastedTicks:= Ticks;
   127             MadeActions:= Actions;
   128             MadeActions:= Actions;
   128             Hedgehog:= Me;
   129             Hedgehog:= Me;
   145 
   146 
   146 var Actions: TActions;
   147 var Actions: TActions;
   147     ticks, maxticks, steps: Longword;
   148     ticks, maxticks, steps: Longword;
   148     BaseRate, BestRate, Rate: integer;
   149     BaseRate, BestRate, Rate: integer;
   149     GoInfo: TGoInfo;
   150     GoInfo: TGoInfo;
       
   151     CanGo: boolean;
       
   152     AltMe: TGear;
   150 begin
   153 begin
   151 Actions.Count:= 0;
   154 Actions.Count:= 0;
   152 Actions.Pos:= 0;
   155 Actions.Pos:= 0;
   153 Actions.Score:= 0;
   156 Actions.Score:= 0;
   154 Stack.Count:= 0;
   157 Stack.Count:= 0;
   155 
   158 
   156 Push(0, Actions, Me^, aia_Left);
   159 Push(0, Actions, Me^, aia_Left);
   157 Push(0, Actions, Me^, aia_Right);
   160 Push(0, Actions, Me^, aia_Right);
   158 
   161 
   159 if (Me.State and gstAttacked) = 0 then maxticks:= TurnTimeLeft - 5000
   162 if (Me.State and gstAttacked) = 0 then maxticks:= max(0, integer(TurnTimeLeft) - 10000)
   160                                   else maxticks:= TurnTimeLeft;
   163                                   else maxticks:= TurnTimeLeft;
   161 
   164 
   162 if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me);
   165 if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me);
   163 BestRate:= RatePlace(Me);
   166 BestRate:= RatePlace(Me);
   164 BaseRate:= max(BestRate, 0);
   167 BaseRate:= max(BestRate, 0);
   169     AddAction(Actions, Me.Message, aim_push, 250);
   172     AddAction(Actions, Me.Message, aim_push, 250);
   170     AddAction(Actions, aia_WaitX, round(Me.X), 0);
   173     AddAction(Actions, aia_WaitX, round(Me.X), 0);
   171     AddAction(Actions, Me.Message, aim_release, 0);
   174     AddAction(Actions, Me.Message, aim_release, 0);
   172     steps:= 0;
   175     steps:= 0;
   173     
   176     
   174     while HHGo(Me, GoInfo) do
   177     while true do
   175        begin
   178        begin
       
   179        CanGo:= HHGo(Me, @AltMe, GoInfo);
   176        inc(ticks, GoInfo.Ticks);
   180        inc(ticks, GoInfo.Ticks);
   177        if ticks > maxticks then break;
   181        if ticks > maxticks then break;
       
   182        if GoInfo.JumpType = jmpHJump then // hjump support
       
   183           if Push(ticks, Actions, AltMe, Me^.Message) then
       
   184              with Stack.States[Pred(Stack.Count)] do
       
   185                   begin
       
   186                   AddAction(MadeActions, aia_HJump, 0, 305);
       
   187                   AddAction(MadeActions, aia_HJump, 0, 350);
       
   188                   end;
       
   189        if GoInfo.JumpType = jmpLJump then // ljump support
       
   190           if Push(ticks, Actions, AltMe, Me^.Message) then
       
   191              with Stack.States[Pred(Stack.Count)] do
       
   192                   AddAction(MadeActions, aia_LJump, 0, 305);
       
   193        if not CanGo then break;
   178        inc(steps);
   194        inc(steps);
   179        Actions.actions[Actions.Count - 2].Param:= round(Me.X);
   195        Actions.actions[Actions.Count - 2].Param:= round(Me.X);
   180        Rate:= RatePlace(Me);
   196        Rate:= RatePlace(Me);
   181        if Rate > BestRate then
   197        if Rate > BestRate then
   182           begin
   198           begin
   185           Me.State:= Me.State or gstAttacked // we have better place, go there and don't use ammo
   201           Me.State:= Me.State or gstAttacked // we have better place, go there and don't use ammo
   186           end
   202           end
   187        else if Rate < BestRate then break;
   203        else if Rate < BestRate then break;
   188        if ((Me.State and gstAttacked) = 0)
   204        if ((Me.State and gstAttacked) = 0)
   189            and ((steps mod 4) = 0) then TestAmmos(Actions, Me);
   205            and ((steps mod 4) = 0) then TestAmmos(Actions, Me);
   190        if GoInfo.FallTicks >= FallTicksForBranching then
   206        if GoInfo.FallPix >= FallPixForBranching then
   191           Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
   207           Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
   192        if StopThinking then exit
   208        if StopThinking then exit
   193        end;
   209        end;
   194 
   210 
   195     if BestRate > BaseRate then exit
   211     if BestRate > BaseRate then exit
   209 if (Me.State and gstAttacked) = 0 then
   225 if (Me.State and gstAttacked) = 0 then
   210    if Targets.Count > 0 then
   226    if Targets.Count > 0 then
   211       begin
   227       begin
   212       Walk(@WalkMe);
   228       Walk(@WalkMe);
   213       if (StartTicks > GameTicks - 1500) then SDL_Delay(2000);
   229       if (StartTicks > GameTicks - 1500) then SDL_Delay(2000);
   214       end else OutError('AI: no targets!?')
   230       end else
   215 else begin
   231 else begin
   216       Walk(@WalkMe);
   232       Walk(@WalkMe);
   217       while (not StopThinking) and (BestActions.Count = 0) do
   233       while (not StopThinking) and (BestActions.Count = 0) do
   218             begin
   234             begin
   219             SDL_Delay(100);
   235             SDL_Delay(100);
   233 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit;
   249 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit;
   234 Me.State:= Me.State or gstHHThinking;
   250 Me.State:= Me.State or gstHHThinking;
   235 StopThinking:= false;
   251 StopThinking:= false;
   236 ThinkingHH:= Me;
   252 ThinkingHH:= Me;
   237 FillTargets;
   253 FillTargets;
       
   254 if Targets.Count = 0 then
       
   255    begin
       
   256    OutError('AI: no targets!?');
       
   257    exit
       
   258    end;
   238 FillBonuses((Me.State and gstAttacked) <> 0);
   259 FillBonuses((Me.State and gstAttacked) <> 0);
   239 for a:= Low(TAmmoType) to High(TAmmoType) do
   260 for a:= Low(TAmmoType) to High(TAmmoType) do
   240     CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me.Hedgehog), a);
   261     CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me.Hedgehog), a);
   241 {$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF}
   262 {$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF}
   242 ThinkThread:= SDL_CreateThread(@Think, Me)
   263 ThinkThread:= SDL_CreateThread(@Think, Me)