hedgewars/uAI.pas
changeset 75 d2b737858ff7
parent 74 42257fee61ae
child 80 3c3dc6a148ca
equal deleted inserted replaced
74:42257fee61ae 75:d2b737858ff7
    41 uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc;
    41 uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc;
    42 
    42 
    43 var BestActions: TActions;
    43 var BestActions: TActions;
    44     ThinkThread: PSDL_Thread = nil;
    44     ThinkThread: PSDL_Thread = nil;
    45     StopThinking: boolean;
    45     StopThinking: boolean;
       
    46     CanUseAmmo: array [TAmmoType] of boolean;
    46 
    47 
    47 procedure FreeActionsList;
    48 procedure FreeActionsList;
    48 begin
    49 begin
    49 if ThinkThread <> nil then
    50 if ThinkThread <> nil then
    50    begin
    51    begin
    63     a, aa: TAmmoType;
    64     a, aa: TAmmoType;
    64 begin
    65 begin
    65 for i:= 0 to Pred(Targets.Count) do
    66 for i:= 0 to Pred(Targets.Count) do
    66     if Targets.ar[i].Score >= 0 then
    67     if Targets.ar[i].Score >= 0 then
    67        begin
    68        begin
    68        if (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0)
    69        with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
    69           then with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
    70             a:= Ammo[CurSlot, CurAmmo].AmmoType;
    70                     a:= Ammo[CurSlot, CurAmmo].AmmoType
       
    71           else a:= Low(TAmmoType);
       
    72        aa:= a;
    71        aa:= a;
    73        repeat
    72        repeat
    74         if Assigned(AmmoTests[a]) then
    73         if CanUseAmmo[a] then
    75            begin
    74            begin
    76            Score:= AmmoTests[a](Me, Targets.ar[i].Point, Time, Angle, Power, ExplX, ExplY, ExplR);
    75            Score:= AmmoTests[a](Me, Targets.ar[i].Point, Time, Angle, Power, ExplX, ExplY, ExplR);
    77            if Actions.Score + Score + Targets.ar[i].Score > BestActions.Score then
    76            if Actions.Score + Score + Targets.ar[i].Score > BestActions.Score then
    78               begin
    77               begin
    79               BestActions:= Actions;
    78               BestActions:= Actions;
   103        until (a = aa) or (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0)
   102        until (a = aa) or (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0)
   104        end
   103        end
   105 end;
   104 end;
   106 
   105 
   107 procedure Walk(Me: PGear);
   106 procedure Walk(Me: PGear);
       
   107 const FallTicksForBranching = cHHRadius * 2 + 8;
       
   108       cBranchStackSize = 8;
       
   109       
       
   110 type TStackEntry = record
       
   111                    WastedTicks: Longword;
       
   112                    MadeActions: TActions;
       
   113                    Hedgehog: TGear;
       
   114                    end;
       
   115                    
       
   116 var Stack: record
       
   117            Count: Longword;
       
   118            States: array[0..Pred(cBranchStackSize)] of TStackEntry;
       
   119            end;
       
   120 
       
   121     procedure Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer);
       
   122     begin
       
   123     if Stack.Count < cBranchStackSize then
       
   124        with Stack.States[Stack.Count] do
       
   125             begin
       
   126             WastedTicks:= Ticks;
       
   127             MadeActions:= Actions;
       
   128             Hedgehog:= Me;
       
   129             Hedgehog.Message:= Dir;
       
   130             inc(Stack.Count)
       
   131             end
       
   132     end;
       
   133 
       
   134     procedure Pop(out Ticks: Longword; out Actions: TActions; out Me: TGear);
       
   135     begin
       
   136     dec(Stack.Count);
       
   137     with Stack.States[Stack.Count] do
       
   138          begin
       
   139          Ticks:= WastedTicks;
       
   140          Actions:= MadeActions;
       
   141          Me:= Hedgehog
       
   142          end
       
   143     end;
       
   144 
       
   145 
   108 var Actions: TActions;
   146 var Actions: TActions;
   109     BackMe: TGear;
   147     ticks, maxticks, steps: Longword;
   110     Dir, steps, maxsteps: integer;
   148     BaseRate, BestRate, Rate: integer;
   111     BestRate, Rate: integer;
   149     GoInfo: TGoInfo;
   112 begin
   150 begin
   113 Actions.Score:= 0;
       
   114 Actions.Count:= 0;
   151 Actions.Count:= 0;
   115 Actions.Pos:= 0;
   152 Actions.Pos:= 0;
   116 BestActions.Count:= 0;
   153 Actions.Score:= 0;
   117 if (Me.State and gstAttacked) = 0 then maxsteps:= (TurnTimeLeft - 4000) div cHHStepTicks
   154 Stack.Count:= 0;
   118                                   else maxsteps:= TurnTimeLeft div cHHStepTicks;
   155 
   119 BackMe:= Me^;
   156 Push(0, Actions, Me^, aia_Left);
       
   157 Push(0, Actions, Me^, aia_Right);
       
   158 
       
   159 if (Me.State and gstAttacked) = 0 then maxticks:= TurnTimeLeft - 5000
       
   160                                   else maxticks:= TurnTimeLeft;
       
   161 
   120 if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me);
   162 if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me);
   121 BestRate:= RatePlace(Me);
   163 BestRate:= RatePlace(Me);
   122 for Dir:= aia_Left to aia_Right do
   164 BaseRate:= max(BestRate, 0);
       
   165 
       
   166 while (Stack.Count > 0) and not StopThinking do
   123     begin
   167     begin
   124     Me.Message:= Dir;
   168     Pop(ticks, Actions, Me^);
       
   169     AddAction(Actions, Me.Message, aim_push, 250);
       
   170     AddAction(Actions, aia_WaitX, round(Me.X), 0);
       
   171     AddAction(Actions, Me.Message, aim_release, 0);
   125     steps:= 0;
   172     steps:= 0;
   126     while HHGo(Me) and (steps < maxsteps) do
   173     
       
   174     while HHGo(Me, GoInfo) do
   127        begin
   175        begin
       
   176        inc(ticks, GoInfo.Ticks);
       
   177        if ticks > maxticks then break;
   128        inc(steps);
   178        inc(steps);
   129        Actions.Count:= 0;
   179        Actions.actions[Actions.Count - 2].Param:= round(Me.X);
   130        AddAction(Actions, Dir, aim_push, 250);
       
   131        AddAction(Actions, aia_WaitX, round(Me.X), 0);
       
   132        AddAction(Actions, Dir, aim_release, 0);
       
   133        Rate:= RatePlace(Me);
   180        Rate:= RatePlace(Me);
   134        if Rate > BestRate then
   181        if Rate > BestRate then
   135           begin
   182           begin
   136           BestActions:= Actions;
   183           BestActions:= Actions;
   137           BestRate:= Rate;
   184           BestRate:= Rate;
   138           Me.State:= Me.State or gstAttacked // we have better place, go there and don't use ammo
   185           Me.State:= Me.State or gstAttacked // we have better place, go there and don't use ammo
   139           end
   186           end
   140        else if Rate < BestRate then
   187        else if Rate < BestRate then break;
   141                if BestRate > 0 then exit
       
   142                                else break;
       
   143        if ((Me.State and gstAttacked) = 0)
   188        if ((Me.State and gstAttacked) = 0)
   144            and ((steps mod 4) = 0) then TestAmmos(Actions, Me);
   189            and ((steps mod 4) = 0) then TestAmmos(Actions, Me);
   145        if StopThinking then exit;
   190        if GoInfo.FallTicks >= FallTicksForBranching then
       
   191           Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
       
   192        if StopThinking then exit
   146        end;
   193        end;
   147     Me^:= BackMe
   194 
       
   195     if BestRate > BaseRate then exit
   148     end
   196     end
   149 end;
   197 end;
   150 
   198 
   151 procedure Think(Me: PGear); cdecl;
   199 procedure Think(Me: PGear); cdecl;
   152 var BackMe, WalkMe: TGear;
   200 var BackMe, WalkMe: TGear;
   170             begin
   218             begin
   171             SDL_Delay(100);
   219             SDL_Delay(100);
   172             FillBonuses(true);
   220             FillBonuses(true);
   173             WalkMe:= BackMe;
   221             WalkMe:= BackMe;
   174             Walk(@WalkMe)
   222             Walk(@WalkMe)
   175             end;
   223             end
   176       AwareOfExplosion(0, 0, 0)
       
   177       end;
   224       end;
   178 
   225 
   179 Me.State:= Me.State and not gstHHThinking;
   226 Me.State:= Me.State and not gstHHThinking;
   180 ThinkThread:= nil
   227 ThinkThread:= nil
   181 end;
   228 end;
   182 
   229 
   183 procedure StartThink(Me: PGear);
   230 procedure StartThink(Me: PGear);
       
   231 var a: TAmmoType;
   184 begin
   232 begin
   185 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit;
   233 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit;
   186 Me.State:= Me.State or gstHHThinking;
   234 Me.State:= Me.State or gstHHThinking;
   187 StopThinking:= false;
   235 StopThinking:= false;
   188 ThinkingHH:= Me;
   236 ThinkingHH:= Me;
   189 FillTargets;
   237 FillTargets;
   190 FillBonuses((Me.State and gstAttacked) <> 0);
   238 FillBonuses((Me.State and gstAttacked) <> 0);
       
   239 for a:= Low(TAmmoType) to High(TAmmoType) do
       
   240     CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me.Hedgehog), a);
   191 {$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF}
   241 {$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF}
   192 ThinkThread:= SDL_CreateThread(@Think, Me)
   242 ThinkThread:= SDL_CreateThread(@Think, Me)
   193 end;
   243 end;
   194 
   244 
   195 procedure ProcessBot;
   245 procedure ProcessBot;
   197 with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
   247 with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
   198      if (Gear <> nil)
   248      if (Gear <> nil)
   199         and ((Gear.State and gstHHDriven) <> 0)
   249         and ((Gear.State and gstHHDriven) <> 0)
   200         and (TurnTimeLeft < 29990)
   250         and (TurnTimeLeft < 29990)
   201         and ((Gear.State and gstHHThinking) = 0) then
   251         and ((Gear.State and gstHHThinking) = 0) then
   202            if (BestActions.Pos = BestActions.Count) then StartThink(Gear)
   252            if (BestActions.Pos >= BestActions.Count) then StartThink(Gear)
   203                                                     else ProcessAction(BestActions, Gear)
   253                                                      else ProcessAction(BestActions, Gear)
   204 end;
   254 end;
   205 
   255 
   206 end.
   256 end.