hedgewars/uAIMisc.pas
changeset 8950 3bf81ed1f984
parent 8939 b26aaf28c920
child 8951 95dd846caf5d
equal deleted inserted replaced
8949:fac5a075f021 8950:3bf81ed1f984
    32 
    32 
    33 type TTarget = record
    33 type TTarget = record
    34     Point: TPoint;
    34     Point: TPoint;
    35     Score: LongInt;
    35     Score: LongInt;
    36     skip, matters, dead: boolean;
    36     skip, matters, dead: boolean;
       
    37     Kind: TGearType;
    37     end;
    38     end;
    38 TTargets = record
    39 TTargets = record
    39     Count: Longword;
    40     Count: Longword;
    40     ar: array[0..Pred(cMaxHHs)] of TTarget;
    41     ar: array[0..Pred(256)] of TTarget;
    41     reset: boolean;
    42     reset: boolean;
    42     end;
    43     end;
    43 TJumpType = (jmpNone, jmpHJump, jmpLJump);
    44 TJumpType = (jmpNone, jmpHJump, jmpLJump);
    44 TGoInfo = record
    45 TGoInfo = record
    45     Ticks: Longword;
    46     Ticks: Longword;
    68 function  TraceShoveFall(x, y, dX, dY: Real): LongInt;
    69 function  TraceShoveFall(x, y, dX, dY: Real): LongInt;
    69 
    70 
    70 function  RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline;
    71 function  RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline;
    71 function  RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline;
    72 function  RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline;
    72 function  RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
    73 function  RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
    73 function  RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
    74 function  RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
    74 function  RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; inline;
    75 function  RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
    75 function  RealRateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
       
    76 function  RateHammer(Me: PGear): LongInt;
    76 function  RateHammer(Me: PGear): LongInt;
    77 
    77 
    78 function  HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
    78 function  HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
    79 function  AIrndSign(num: LongInt): LongInt;
    79 function  AIrndSign(num: LongInt): LongInt;
    80 
    80 
   112 Targets.reset:= false;
   112 Targets.reset:= false;
   113 end;
   113 end;
   114 procedure FillTargets;
   114 procedure FillTargets;
   115 var i, t: Longword;
   115 var i, t: Longword;
   116     f, e: LongInt;
   116     f, e: LongInt;
       
   117     iter: PGear;
   117 begin
   118 begin
   118 Targets.Count:= 0;
   119 Targets.Count:= 0;
   119 Targets.reset:= false;
   120 Targets.reset:= false;
   120 f:= 0;
   121 f:= 0;
   121 e:= 0;
   122 e:= 0;
   122 for t:= 0 to Pred(TeamsCount) do
   123 iter:= GearsList;
   123     with TeamsArray[t]^ do
   124 while iter <> nil do
   124         if not hasGone then
   125     begin
   125             begin
   126     if  ((iter^.Kind = gtHedgehog) and
   126             for i:= 0 to cMaxHHIndex do
   127             (iter <> ThinkingHH) and
   127                 if (Hedgehogs[i].Gear <> nil)
   128             (iter^.Health > iter^.Damage) and
   128                 and (Hedgehogs[i].Gear <> ThinkingHH)
   129             not(iter^.Hedgehog^.Team^.hasgone)) or
   129                 and (Hedgehogs[i].Gear^.Health > Hedgehogs[i].Gear^.Damage)
   130         ((iter^.Kind = gtExplosives) and
   130                     then
   131             (iter^.Health > iter^.Damage)) or
   131                     begin
   132         ((iter^.Kind = gtMine) and
   132                     with Targets.ar[Targets.Count], Hedgehogs[i] do
   133             (iter^.Health = 0) and
   133                         begin
   134             (iter^.Damage < 35)) and
   134                         skip:= false;
   135         (Targets.Count < 256) then
   135                         dead:= false;
   136         begin
   136                         matters:= (Hedgehogs[i].Gear^.AIHints and aihDoesntMatter) = 0;
   137         with Targets.ar[Targets.Count] do
   137 
   138             begin
   138                         Point.X:= hwRound(Gear^.X);
   139             skip:= false;
   139                         Point.Y:= hwRound(Gear^.Y);
   140             dead:= false;
   140                         if Clan <> CurrentTeam^.Clan then
   141             Kind:= iter^.Kind;
   141                             begin
   142             matters:= (iter^.AIHints and aihDoesntMatter) = 0;
   142                             Score:= Gear^.Health - Gear^.Damage;
   143 
   143                             inc(e)
   144             Point.X:= hwRound(iter^.X);
   144                             end else
   145             Point.Y:= hwRound(iter^.Y);
   145                             begin
   146             if (iter^.Kind = gtHedgehog) then
   146                             Score:= Gear^.Damage - Gear^.Health;
   147                 if (iter^.Hedgehog^.Team^.Clan = CurrentTeam^.Clan) then
   147                             inc(f)
   148                     begin
   148                             end
   149                     Score:= iter^.Damage - iter^.Health;
   149                         end;
   150                     inc(f)
   150                     inc(Targets.Count)
   151                     end
   151                     end;
   152                 else 
   152             end;
   153                     begin
       
   154                     Score:= iter^.Health - iter^.Damage;
       
   155                     inc(e)
       
   156                     end
       
   157             else if iter^.Kind = gtExplosives then Score:= iter^.Health - iter^.Damage
       
   158             else if iter^.Kind = gtMine then Score:= max(0,35-iter^.Damage)
       
   159             end;
       
   160         inc(Targets.Count)
       
   161         end;
       
   162     iter:= iter^.NextGear
       
   163     end;
   153 
   164 
   154 if e > f then friendlyfactor:= 300 + (e - f) * 30
   165 if e > f then friendlyfactor:= 300 + (e - f) * 30
   155 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e))
   166 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e))
   156 end;
   167 end;
   157 
   168 
   461                     if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
   472                     if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
   462                        (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
   473                        (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
   463                          fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0) * dmgMod)
   474                          fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0) * dmgMod)
   464                     else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure) * dmgMod)
   475                     else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure) * dmgMod)
   465                     end;
   476                     end;
   466                 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   477                 if Kind = gtHedgehog then
   467                     if Score > 0 then
   478                     begin
   468                         inc(rate, (KillScore + Score div 10) * 1024)   // Add a bit of a bonus for bigger hog drownings
   479                     if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
       
   480                         begin
       
   481                         if Score > 0 then
       
   482                             inc(rate, (KillScore + Score div 10) * 1024)   // Add a bit of a bonus for bigger hog drownings
       
   483                         else
       
   484                             dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs
       
   485                         end
       
   486                     else if (dmg+fallDmg) >= abs(Score) then
       
   487                         begin
       
   488                         dead:= true;
       
   489                         Targets.reset:= true;
       
   490                         if dX < 0.035 then
       
   491                             inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or (Flags and afTrackFall)));
       
   492                         if Score > 0 then
       
   493                              inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill
       
   494                         else dec(rate, KillScore * friendlyfactor div 100 * 1024)
       
   495                         end
   469                     else
   496                     else
   470                         dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs
   497                         begin
   471                 else if (dmg+fallDmg) >= abs(Score) then
   498                         if Score > 0 then
       
   499                              inc(rate, (dmg + fallDmg) * 1024)
       
   500                         else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024)
       
   501                         end
       
   502                     end
       
   503 // FIXME - need to make TraceFall calculate damage for barrels/mines correctly
       
   504                 else if (Kind <> gtHedgehog) and (FallDmg >= 0) and ((dmg+fallDmg) >= Score) then
   472                     begin
   505                     begin
   473                     dead:= true;
   506                     dead:= true;
   474                     Targets.reset:= true;
   507                     Targets.reset:= true;
   475                     if dX < 0.035 then
   508                     if Kind = gtExplosives then
   476                         inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or (Flags and afTrackFall)));
   509                          inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)))
   477                     if Score > 0 then
   510                     else inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall)))
   478                         inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill
       
   479                     else
       
   480                         dec(rate, KillScore * friendlyfactor div 100 * 1024)
       
   481                     end
   511                     end
   482                 else
   512                 end
   483                     if Score > 0 then
       
   484                         inc(rate, (dmg + fallDmg) * 1024)
       
   485                     else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024)
       
   486                 end;
       
   487             end;
   513             end;
   488 
   514 
   489 if hadSkips and (rate = 0) then
   515 if hadSkips and (rate = 0) then
   490     RealRateExplosion:= BadTurn
   516     RealRateExplosion:= BadTurn
   491     else
   517     else
   492     RealRateExplosion:= rate;
   518     RealRateExplosion:= rate;
   493 end;
   519 end;
   494 
   520 
   495 function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
   521 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
   496 var i, fallDmg, dmg, rate: LongInt;
   522 var i, fallDmg, dmg, rate: LongInt;
   497     dX, dY: real;
   523     dX, dY, pX, pY: real;
   498 begin
   524 begin
   499 fallDmg:= 0;
   525 fallDmg:= 0;
   500 dX:= gdX * 0.01 * kick;
   526 dX:= gdX * 0.01 * kick;
   501 dY:= gdY * 0.01 * kick;
   527 dY:= gdY * 0.01 * kick;
   502 rate:= 0;
   528 rate:= 0;
   510         if abs(Point.x - x) + abs(Point.y - y) < r then
   536         if abs(Point.x - x) + abs(Point.y - y) < r then
   511             dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
   537             dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
   512 
   538 
   513         if dmg > 0 then
   539         if dmg > 0 then
   514             begin
   540             begin
       
   541             pX:= Point.x;
       
   542             pY:= Point.y;
   515             if (Flags and afSetSkip <> 0) then skip:= true;
   543             if (Flags and afSetSkip <> 0) then skip:= true;
   516             if (Flags and afTrackFall <> 0) and (Score > 0) then
   544             if (Flags and afTrackFall <> 0) and (Score > 0) then
   517                 fallDmg:= trunc(TraceShoveFall(Point.x, Point.y - 2, dX, dY) * dmgMod);
   545                 fallDmg:= trunc(TraceShoveFall(pX, pY - 2, dX, dY) * dmgMod);
   518             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   546             if Kind = gtHedgehog then
   519                 if Score > 0 then
   547                 begin
   520                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
   548                 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
       
   549                     begin
       
   550                     if Score > 0 then
       
   551                         inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
       
   552                     else
       
   553                         dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
       
   554                     end
       
   555                 else if power+fallDmg >= abs(Score) then
       
   556                     begin
       
   557                     dead:= true;
       
   558                     Targets.reset:= true;
       
   559                     if dX < 0.035 then
       
   560                         inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or (Flags and afTrackFall)) div 1024);
       
   561                     if Score > 0 then
       
   562                         inc(rate, KillScore)
       
   563                     else
       
   564                         dec(rate, KillScore * friendlyfactor div 100)
       
   565                     end
   521                 else
   566                 else
   522                     dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
   567                     begin
   523             else if power+fallDmg >= abs(Score) then
   568                     if Score > 0 then
   524                 if Score > 0 then
   569                         inc(rate, power+fallDmg)
   525                     inc(rate, KillScore)
   570                     else
   526                 else
   571                         dec(rate, (power+fallDmg) * friendlyfactor div 100)
   527                     dec(rate, KillScore * friendlyfactor div 100)
   572                     end
   528             else
   573                 end
   529                 if Score > 0 then
   574 // FIXME - need to make TraceFall calculate damage for barrels/mines correctly
   530                     inc(rate, power+fallDmg)
   575             else if (Kind <> gtHedgehog) and (fallDmg >= 0) and ((power+fallDmg) >= Score) then
   531                 else
   576                 begin
   532                     dec(rate, (power+fallDmg) * friendlyfactor div 100)
   577                 dead:= true;
   533             end;
   578                 Targets.reset:= true;
       
   579                 if Kind = gtExplosives then
       
   580                      inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) div 1024)
       
   581                 else inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall)) div 1024)
       
   582                 end
       
   583             end
   534         end;
   584         end;
   535 RateShove:= rate * 1024
   585 RateShove:= rate * 1024
   536 end;
   586 end;
   537 
   587 
   538 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; inline;
   588 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
   539 begin
       
   540     RateShotgun:= RealRateShotgun(Me, gdX, gdY, x, y);
       
   541     ResetTargets;
       
   542 end;
       
   543 function RealRateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
       
   544 var i, dmg, fallDmg, baseDmg, rate, erasure: LongInt;
   589 var i, dmg, fallDmg, baseDmg, rate, erasure: LongInt;
   545     pX, pY, dX, dY: real;
   590     pX, pY, dX, dY: real;
   546     hadSkips: boolean;
   591     hadSkips: boolean;
   547 begin
   592 begin
   548 rate:= 0;
   593 rate:= 0;
   587                 else dX:= dX + 0.01;
   632                 else dX:= dX + 0.01;
   588                 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
   633                 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
   589                    (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
   634                    (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
   590                      fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0) * dmgMod)
   635                      fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0) * dmgMod)
   591                 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure) * dmgMod);
   636                 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure) * dmgMod);
   592                 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   637                 if Kind = gtHedgehog then
   593                     if Score > 0 then
   638                     begin
   594                         inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
   639                     if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   595                     else
   640                         begin
   596                         dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
   641                         if Score > 0 then
   597                 else if (dmg+fallDmg) >= abs(Score) then
   642                             inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
       
   643                         else
       
   644                             dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
       
   645                         end
       
   646                     else if (dmg+fallDmg) >= abs(Score) then
       
   647                         begin
       
   648                         dead:= true;
       
   649                         Targets.reset:= true;
       
   650                         if dX < 0.035 then
       
   651                             inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall) div 1024);
       
   652                         if Score > 0 then
       
   653                             inc(rate, KillScore)
       
   654                         else
       
   655                             dec(rate, KillScore * friendlyfactor div 100)
       
   656                         end
       
   657                     else if Score > 0 then
       
   658                          inc(rate, dmg+fallDmg)
       
   659                     else dec(rate, (dmg+fallDmg) * friendlyfactor div 100)
       
   660                     end
       
   661 // FIXME - need to make TraceFall calculate damage for barrels/mines correctly
       
   662                 else if (Kind <> gtHedgehog) and (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then
   598                     begin
   663                     begin
   599                     dead:= true;
   664                     dead:= true;
   600                     Targets.reset:= true;
   665                     Targets.reset:= true;
   601                     if dX < 0.035 then
   666                     if Kind = gtExplosives then
   602                         inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall) div 1024);
   667                          inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or afTrackFall) div 1024)
   603                     if Score > 0 then
   668                     else inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or afTrackFall) div 1024)
   604                         inc(rate, KillScore)
       
   605                     else
       
   606                         dec(rate, KillScore * friendlyfactor div 100)
       
   607                     end
   669                     end
   608                 else
   670                 end
   609                     if Score > 0 then
       
   610                         inc(rate, dmg+fallDmg)
       
   611                 else
       
   612                     dec(rate, (dmg+fallDmg) * friendlyfactor div 100)
       
   613                 end;
       
   614             end;
   671             end;
   615 
   672 
   616 if hadSkips and (rate = 0) then
   673 if hadSkips and (rate = 0) then
   617     RealRateShotgun:= BadTurn
   674     RateShotgun:= BadTurn
   618     else
   675     else
   619     RealRateShotgun:= rate * 1024;
   676     RateShotgun:= rate * 1024;
       
   677     ResetTargets;
   620 end;
   678 end;
   621 
   679 
   622 function RateHammer(Me: PGear): LongInt;
   680 function RateHammer(Me: PGear): LongInt;
   623 var x, y, i, r, rate: LongInt;
   681 var x, y, i, r, rate: LongInt;
   624 begin
   682 begin