hedgewars/uAI.pas
changeset 7231 f484455dd055
parent 7216 53f5e48b8375
child 7250 304d3d98662e
equal deleted inserted replaced
7198:5debd5fe526e 7231:f484455dd055
   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                 if Push(ticks, Actions, AltMe, Me^.Message) then
   265                     end;
   288                     with Stack.States[Pred(Stack.Count)] do
   266         if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support
   289                         AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
   267             if Push(ticks, Actions, AltMe, Me^.Message) then
   290 
   268                 with Stack.States[Pred(Stack.Count)] do
   291             // 'not CanGO' means we can't go straight, possible jumps are checked above
   269                     AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
   292             if not CanGo then
   270 
   293                 break;
   271         // 'not CanGO' means we can't go straight, possible jumps are checked above
   294             
   272         if not CanGo then
   295              inc(steps);
   273             break;
   296              Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
   274         
   297              Rate:= RatePlace(Me);
   275          inc(steps);
   298              if Rate > BestRate then
   276          Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
   299                 begin
   277          Rate:= RatePlace(Me);
   300                 BestActions:= Actions;
   278          if Rate > BestRate then
   301                 BestActions.isWalkingToABetterPlace:= true;
   279             begin
   302                 BestRate:= Rate;
   280             BestActions:= Actions;
   303                 Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
   281             BestActions.isWalkingToABetterPlace:= true;
   304                 end
   282             BestRate:= Rate;
   305             else if Rate < BestRate then
   283             Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
   306                 break;
   284             end
   307             if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then
   285         else if Rate < BestRate then
   308                 TestAmmos(Actions, Me, true);
   286             break;
   309             if GoInfo.FallPix >= FallPixForBranching then
   287         if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then
   310                 Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
   288             TestAmmos(Actions, Me, true);
   311             end {while};
   289         if GoInfo.FallPix >= FallPixForBranching then
   312 
   290             Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
   313         if BestRate > BaseRate then
   291         end {while};
   314             exit
   292 
       
   293     if BestRate > BaseRate then
       
   294         exit
       
   295         end {while}
   315         end {while}
       
   316     end {if}
   296 end;
   317 end;
   297 
   318 
   298 function Think(Me: Pointer): ptrint;
   319 function Think(Me: Pointer): ptrint;
   299 var BackMe, WalkMe: TGear;
   320 var BackMe, WalkMe: TGear;
   300     switchCount: LongInt;
   321     switchCount: LongInt;
   412 BeginThread(@Think, Me, ThinkThread);
   433 BeginThread(@Think, Me, ThinkThread);
   413 {$ENDIF}
   434 {$ENDIF}
   414 AddFileLog('Thread started');
   435 AddFileLog('Thread started');
   415 end;
   436 end;
   416 
   437 
       
   438 //var scoreShown: boolean = false;
       
   439 
   417 procedure ProcessBot;
   440 procedure ProcessBot;
   418 const cStopThinkTime = 40;
   441 const cStopThinkTime = 40;
   419 begin
   442 begin
   420 with CurrentHedgehog^ do
   443 with CurrentHedgehog^ do
   421     if (Gear <> nil)
   444     if (Gear <> nil)
   428                 if Gear^.Message <> 0 then
   451                 if Gear^.Message <> 0 then
   429                     begin
   452                     begin
   430                     StopMessages(Gear^.Message);
   453                     StopMessages(Gear^.Message);
   431                     TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true);
   454                     TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true);
   432                     end;
   455                     end;
       
   456                     
   433                 if Gear^.Message <> 0 then
   457                 if Gear^.Message <> 0 then
   434                     exit;
   458                     exit;
       
   459                     
       
   460                 //scoreShown:= false;   
   435                 StartThink(Gear);
   461                 StartThink(Gear);
   436                 StartTicks:= GameTicks
   462                 StartTicks:= GameTicks
   437                 
   463                 
   438                 end else
   464             end else
   439                     ProcessAction(BestActions, Gear)
   465                 begin
       
   466                 (*
       
   467                 if not scoreShown then
       
   468                     begin
       
   469                     if BestActions.Score > 0 then ParseCommand('/say Expected score = ' + inttostr(BestActions.Score div 1024), true);
       
   470                     scoreShown:= true
       
   471                     end;*)
       
   472                 ProcessAction(BestActions, Gear)
       
   473                 end
   440         else if ((GameTicks - StartTicks) > cMaxAIThinkTime)
   474         else if ((GameTicks - StartTicks) > cMaxAIThinkTime)
   441         or (TurnTimeLeft <= cStopThinkTime) then
   475             or (TurnTimeLeft <= cStopThinkTime) then
   442             StopThinking:= true
   476                 StopThinking:= true
   443 end;
   477 end;
   444 
   478 
   445 procedure initModule;
   479 procedure initModule;
   446 begin
   480 begin
   447     hasThread:= 0;
   481     hasThread:= 0;