hedgewars/uAI.pas
changeset 7288 5d0704f23a2a
parent 7250 304d3d98662e
child 7375 16ae2e1c9005
equal deleted inserted replaced
7188:580cd247511e 7288:5d0704f23a2a
   109 
   109 
   110 
   110 
   111 procedure TestAmmos(var Actions: TActions; Me: PGear; isMoved: boolean);
   111 procedure TestAmmos(var Actions: TActions; Me: PGear; isMoved: boolean);
   112 var BotLevel: Byte;
   112 var BotLevel: Byte;
   113     ap: TAttackParams;
   113     ap: TAttackParams;
   114     Score, i: LongInt;
   114     Score, i, dAngle: LongInt;
   115     a, aa: TAmmoType;
   115     a, aa: TAmmoType;
   116 begin
   116 begin
   117 BotLevel:= Me^.Hedgehog^.BotLevel;
   117 BotLevel:= Me^.Hedgehog^.BotLevel;
   118 windSpeed:= hwFloat2Float(cWindSpeed);
   118 windSpeed:= hwFloat2Float(cWindSpeed);
   119 
   119 
   151                     else if (ap.Angle < 0) then
   151                     else if (ap.Angle < 0) then
   152                         AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0);
   152                         AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0);
   153                     
   153                     
   154                     if (ap.Time <> 0) then
   154                     if (ap.Time <> 0) then
   155                         AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0);
   155                         AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0);
       
   156                         
   156                     if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then
   157                     if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then
   157                         begin
   158                         begin
   158                         ap.Angle:= LongInt(Me^.Angle) - Abs(ap.Angle);
   159                         dAngle:= LongInt(Me^.Angle) - Abs(ap.Angle);
   159                         if ap.Angle > 0 then
   160                         if dAngle > 0 then
   160                             begin
   161                             begin
   161                             AddAction(BestActions, aia_Up, aim_push, 300 + random(250), 0, 0);
   162                             AddAction(BestActions, aia_Up, aim_push, 300 + random(250), 0, 0);
   162                             AddAction(BestActions, aia_Up, aim_release, ap.Angle, 0, 0)
   163                             AddAction(BestActions, aia_Up, aim_release, dAngle, 0, 0)
   163                             end
   164                             end
   164                         else if ap.Angle < 0 then
   165                         else if dAngle < 0 then
   165                             begin
   166                             begin
   166                             AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0);
   167                             AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0);
   167                             AddAction(BestActions, aia_Down, aim_release, -ap.Angle, 0, 0)
   168                             AddAction(BestActions, aia_Down, aim_release, -dAngle, 0, 0)
   168                             end
   169                             end
   169                         end;
   170                         end;
       
   171                         
   170                     if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
   172                     if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
   171                         begin
   173                         begin
   172                         AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY)
   174                         AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY)
   173                         end;
   175                         end;
   174                     if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then
   176                         
       
   177                     if (Ammoz[a].Ammo.Propz and ammoprop_OscAim) <> 0 then
   175                         begin
   178                         begin
   176                         AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0);
   179                         AddAction(BestActions, aia_attack, aim_push, 350 + random(200), 0, 0);
   177                         AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0);
   180                         AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
   178                         end;
   181                                                 
       
   182                         AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0);
       
   183                         AddAction(BestActions, aia_Down, aim_release, 32, 0, 0);
       
   184                         
       
   185                         AddAction(BestActions, aia_waitAngle, ap.Angle, 250, 0, 0);
       
   186                         AddAction(BestActions, aia_attack, aim_push, 1, 0, 0);
       
   187                         AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
       
   188                         end else
       
   189                         if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then
       
   190                             begin
       
   191                             AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0);
       
   192                             AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0);
       
   193                             end;
       
   194                             
   179                     if ap.ExplR > 0 then
   195                     if ap.ExplR > 0 then
   180                         AddAction(BestActions, aia_AwareExpl, ap.ExplR, 10, ap.ExplX, ap.ExplY);
   196                         AddAction(BestActions, aia_AwareExpl, ap.ExplR, 10, ap.ExplX, ap.ExplY);
   181                     end
   197                     end
   182             end;
   198             end;
   183         if a = High(TAmmoType) then
   199         if a = High(TAmmoType) then
   216     TestAmmos(Actions, Me, false);
   232     TestAmmos(Actions, Me, false);
   217     
   233     
   218 BestRate:= RatePlace(Me);
   234 BestRate:= RatePlace(Me);
   219 BaseRate:= Max(BestRate, 0);
   235 BaseRate:= Max(BestRate, 0);
   220 
   236 
       
   237 // switch to 'skip' if we can't move because of mouse cursor being shown
   221 if (Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
   238 if (Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
   222     AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0);
   239     AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0);
   223 
       
   224 tmp:= random(2) + 1;
       
   225 Push(0, Actions, Me^, tmp);
       
   226 Push(0, Actions, Me^, tmp xor 3);
       
   227     
   240     
   228 while (Stack.Count > 0) and (not StopThinking) and (GameFlags and gfArtillery = 0) do
   241 if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0)) 
       
   242     and (GameFlags and gfArtillery = 0) then
   229     begin
   243     begin
   230     Pop(ticks, Actions, Me^);
   244     tmp:= random(2) + 1;
   231 
   245     Push(0, Actions, Me^, tmp);
   232     AddAction(Actions, Me^.Message, aim_push, 250, 0, 0);
   246     Push(0, Actions, Me^, tmp xor 3);
   233     if (Me^.Message and gmLeft) <> 0 then
       
   234         AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
       
   235     else
       
   236         AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0);
       
   237     
   247     
   238     steps:= 0;
   248     while (Stack.Count > 0) and (not StopThinking) do
   239 
       
   240     while (not StopThinking) do
       
   241         begin
   249         begin
   242 {$HINTS OFF}
   250         Pop(ticks, Actions, Me^);
   243         CanGo:= HHGo(Me, @AltMe, GoInfo);
   251 
   244 {$HINTS ON}
   252         AddAction(Actions, Me^.Message, aim_push, 250, 0, 0);
   245         inc(ticks, GoInfo.Ticks);
   253         if (Me^.Message and gmLeft) <> 0 then
   246         if ticks > maxticks then
   254             AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
   247             break;
   255         else
   248 
   256             AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0);
   249         if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support
   257         
   250             if Push(ticks, Actions, AltMe, Me^.Message) then
   258         steps:= 0;
   251                 with Stack.States[Pred(Stack.Count)] do
   259 
   252                     begin
   260         while (not StopThinking) do
   253                     if Me^.dX.isNegative then
   261             begin
   254                         AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0)
   262     {$HINTS OFF}
   255                     else
   263             CanGo:= HHGo(Me, @AltMe, GoInfo);
   256                         AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0);
   264     {$HINTS ON}
       
   265             inc(ticks, GoInfo.Ticks);
       
   266             if ticks > maxticks then
       
   267                 break;
       
   268 
       
   269             if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support
       
   270                 if Push(ticks, Actions, AltMe, Me^.Message) then
       
   271                     with Stack.States[Pred(Stack.Count)] do
       
   272                         begin
       
   273                         if Me^.dX.isNegative then
       
   274                             AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0)
       
   275                         else
       
   276                             AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0);
       
   277                             
       
   278                         AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0);
       
   279                         AddAction(MadeActions, aia_HJump, 0, 350, 0, 0);
   257                         
   280                         
   258                     AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0);
   281                         if Me^.dX.isNegative then
   259                     AddAction(MadeActions, aia_HJump, 0, 350, 0, 0);
   282                             AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0)
   260                     
   283                         else
   261                     if Me^.dX.isNegative then
   284                             AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0);
   262                         AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0)
   285                         end;
   263                     else
   286             if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support
   264                         AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0);
   287                 begin
   265                     end;
   288                 // push current position so we proceed from it after checking jump opportunities
   266         if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support
   289                 if CanGo then Push(ticks, Actions, Me^, Me^.Message);
   267             if Push(ticks, Actions, AltMe, Me^.Message) then
   290                 // first check where we go after jump
   268                 with Stack.States[Pred(Stack.Count)] do
   291                 if Push(ticks, Actions, AltMe, Me^.Message) then
   269                     AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
   292                     with Stack.States[Pred(Stack.Count)] do
   270 
   293                         AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
   271         // 'not CanGO' means we can't go straight, possible jumps are checked above
   294                 break
   272         if not CanGo then
   295                 end;
   273             break;
   296 
   274         
   297             // 'not CanGO' means we can't go straight, possible jumps are checked above
   275          inc(steps);
   298             if not CanGo then
   276          Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
   299                 break;
   277          Rate:= RatePlace(Me);
   300             
   278          if Rate > BestRate then
   301              inc(steps);
   279             begin
   302              Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
   280             BestActions:= Actions;
   303              Rate:= RatePlace(Me);
   281             BestActions.isWalkingToABetterPlace:= true;
   304              if Rate > BestRate then
   282             BestRate:= Rate;
   305                 begin
   283             Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
   306                 BestActions:= Actions;
   284             end
   307                 BestActions.isWalkingToABetterPlace:= true;
   285         else if Rate < BestRate then
   308                 BestRate:= Rate;
   286             break;
   309                 Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
   287         if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then
   310                 end
   288             TestAmmos(Actions, Me, true);
   311             else if Rate < BestRate then
   289         if GoInfo.FallPix >= FallPixForBranching then
   312                 break;
   290             Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
   313             if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then
   291         end {while};
   314                 TestAmmos(Actions, Me, true);
   292 
   315             if GoInfo.FallPix >= FallPixForBranching then
   293     if BestRate > BaseRate then
   316                 Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
   294         exit
   317             end {while};
       
   318 
       
   319         if BestRate > BaseRate then
       
   320             exit
   295         end {while}
   321         end {while}
       
   322     end {if}
   296 end;
   323 end;
   297 
   324 
   298 function Think(Me: Pointer): ptrint;
   325 function Think(Me: Pointer): ptrint;
   299 var BackMe, WalkMe: TGear;
   326 var BackMe, WalkMe: TGear;
   300     switchCount: LongInt;
   327     switchCount: LongInt;
   412 BeginThread(@Think, Me, ThinkThread);
   439 BeginThread(@Think, Me, ThinkThread);
   413 {$ENDIF}
   440 {$ENDIF}
   414 AddFileLog('Thread started');
   441 AddFileLog('Thread started');
   415 end;
   442 end;
   416 
   443 
       
   444 //var scoreShown: boolean = false;
       
   445 
   417 procedure ProcessBot;
   446 procedure ProcessBot;
   418 const cStopThinkTime = 40;
   447 const cStopThinkTime = 40;
   419 begin
   448 begin
   420 with CurrentHedgehog^ do
   449 with CurrentHedgehog^ do
   421     if (Gear <> nil)
   450     if (Gear <> nil)
   428                 if Gear^.Message <> 0 then
   457                 if Gear^.Message <> 0 then
   429                     begin
   458                     begin
   430                     StopMessages(Gear^.Message);
   459                     StopMessages(Gear^.Message);
   431                     TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true);
   460                     TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true);
   432                     end;
   461                     end;
       
   462                     
   433                 if Gear^.Message <> 0 then
   463                 if Gear^.Message <> 0 then
   434                     exit;
   464                     exit;
       
   465                     
       
   466                 //scoreShown:= false;   
   435                 StartThink(Gear);
   467                 StartThink(Gear);
   436                 StartTicks:= GameTicks
   468                 StartTicks:= GameTicks
   437                 
   469                 
   438                 end else
   470             end else
   439                     ProcessAction(BestActions, Gear)
   471                 begin
       
   472                 (*
       
   473                 if not scoreShown then
       
   474                     begin
       
   475                     if BestActions.Score > 0 then ParseCommand('/say Expected score = ' + inttostr(BestActions.Score div 1024), true);
       
   476                     scoreShown:= true
       
   477                     end;*)
       
   478                 ProcessAction(BestActions, Gear)
       
   479                 end
   440         else if ((GameTicks - StartTicks) > cMaxAIThinkTime)
   480         else if ((GameTicks - StartTicks) > cMaxAIThinkTime)
   441         or (TurnTimeLeft <= cStopThinkTime) then
   481             or (TurnTimeLeft <= cStopThinkTime) then
   442             StopThinking:= true
   482                 StopThinking:= true
   443 end;
   483 end;
   444 
   484 
   445 procedure initModule;
   485 procedure initModule;
   446 begin
   486 begin
   447     hasThread:= 0;
   487     hasThread:= 0;