hedgewars/uAIMisc.pas
changeset 6783 8d9160b85bdb
parent 6782 33009ac4de80
child 6785 a8aa5984185f
equal deleted inserted replaced
6782:33009ac4de80 6783:8d9160b85bdb
    51 procedure FillBonuses(isAfterAttack: boolean; filter: TGearsType = []);
    51 procedure FillBonuses(isAfterAttack: boolean; filter: TGearsType = []);
    52 procedure AwareOfExplosion(x, y, r: LongInt); inline;
    52 procedure AwareOfExplosion(x, y, r: LongInt); inline;
    53 function RatePlace(Gear: PGear): LongInt;
    53 function RatePlace(Gear: PGear): LongInt;
    54 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
    54 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
    55 function TestColl(x, y, r: LongInt): boolean; inline;
    55 function TestColl(x, y, r: LongInt): boolean; inline;
    56 function TraceShoveDrown(Me: PGear; x, y, dX, dY: Real): boolean;
    56 function TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt;
    57 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord = 0): LongInt;
    57 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord = 0): LongInt;
    58 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
    58 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
    59 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
    59 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
    60 function RateHammer(Me: PGear): LongInt;
    60 function RateHammer(Me: PGear): LongInt;
    61 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
    61 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
   258     exit(true);
   258     exit(true);
   259     
   259     
   260 TestCollWithLand:=(((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] > 255)
   260 TestCollWithLand:=(((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] > 255)
   261 end;
   261 end;
   262 
   262 
   263 function TraceDrown(eX, eY: LongInt; x, y, dX, dY: Real; r: LongWord): boolean;
   263 function TraceFall(eX, eY: LongInt; x, y, dX, dY: Real; r: LongWord): LongInt;
   264 var skipLandCheck: boolean;
   264 var skipLandCheck: boolean;
   265     rCorner: real;
   265     rCorner: real;
       
   266     dmg: LongInt;
   266 begin
   267 begin
   267     skipLandCheck:= true;
   268     skipLandCheck:= true;
   268     if x - eX < 0 then dX:= -dX;
   269     if x - eX < 0 then dX:= -dX;
   269     if y - eY < 0 then dY:= -dY;
   270     if y - eY < 0 then dY:= -dY;
   270     // ok. attempt approximate search for an unbroken trajectory into water.  if it continues far enough, assume out of map
   271     // ok. attempt approximate search for an unbroken trajectory into water.  if it continues far enough, assume out of map
   273         begin
   274         begin
   274         x:= x + dX;
   275         x:= x + dX;
   275         y:= y + dY;
   276         y:= y + dY;
   276         dY:= dY + cGravityf;
   277         dY:= dY + cGravityf;
   277         skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner));
   278         skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner));
   278         // consider adding dX/dY calc here for fall damage
   279         if not skipLandCheck and TestCollWithLand(trunc(x), trunc(y), cHHRadius) then
   279         if not skipLandCheck and TestCollWithLand(trunc(x), trunc(y), cHHRadius) then exit(false);
   280             begin
   280         if (y > cWaterLine) or (x > 4096) or (x < 0) then exit(true);
   281             if 0.4 < dY then
   281         end;
   282                 begin
   282 end;
   283                 dmg := 1 + trunc((abs(dY) - 0.4) * 70);
   283 
   284                 if dmg >= 1 then exit(dmg)
   284 function TraceShoveDrown(Me: PGear; x, y, dX, dY: Real): boolean;
   285                 end;
       
   286             exit(0)
       
   287             end;
       
   288         if (y > cWaterLine) or (x > 4096) or (x < 0) then exit(-1); // returning -1 for drowning so it can be considered in the Rate routine
       
   289         end;
       
   290 end;
       
   291 
       
   292 function TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt;
       
   293 var dmg: LongInt;
   285 begin
   294 begin
   286     while true do
   295     while true do
   287         begin
   296         begin
   288         x:= x + dX;
   297         x:= x + dX;
   289         y:= y + dY;
   298         y:= y + dY;
   290         dY:= dY + cGravityf;
   299         dY:= dY + cGravityf;
   291         // consider adding dX/dY calc here for fall damage
   300         // consider adding dX/dY calc here for fall damage
   292         if TestCollExcludingMe(Me, trunc(x), trunc(y), cHHRadius) then exit(false);
   301         if TestCollExcludingMe(Me, trunc(x), trunc(y), cHHRadius) then
   293         if (y > cWaterLine) or (x > 4096) or (x < 0) then exit(true);
   302             begin
       
   303             if 0.4 < dY then
       
   304                 begin
       
   305                 dmg := 1 + trunc((abs(dY) - 0.4) * 70);
       
   306                 if dmg >= 1 then exit(dmg)
       
   307                 end;
       
   308             exit(0)
       
   309             end;
       
   310         if (y > cWaterLine) or (x > 4096) or (x < 0) then exit(-1); // returning -1 for drowning so it can be considered in the Rate routine
   294         end;
   311         end;
   295 end;
   312 end;
   296 
   313 
   297 // Flags are not defined yet but 1 for checking drowning and 2 for assuming land erasure.
   314 // Flags are not defined yet but 1 for checking drowning and 2 for assuming land erasure.
   298 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord = 0): LongInt;
   315 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord = 0): LongInt;
   299 var i, dmg, dmgBase, rate, erasure: LongInt;
   316 var i, fallDmg, dmg, dmgBase, rate, erasure: LongInt;
   300     dX, dY, dmgMod: real;
   317     dX, dY, dmgMod: real;
   301 begin
   318 begin
       
   319 fallDmg:= 0;
   302 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
   320 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
   303 rate:= 0;
   321 rate:= 0;
   304 // add our virtual position
   322 // add our virtual position
   305 with Targets.ar[Targets.Count] do
   323 with Targets.ar[Targets.Count] do
   306     begin
   324     begin
   323             begin
   341             begin
   324             if Flags and 1 <> 0 then
   342             if Flags and 1 <> 0 then
   325                 begin
   343                 begin
   326                 dX:= 0.005 * dmg + 0.01;
   344                 dX:= 0.005 * dmg + 0.01;
   327                 dY:= dX;
   345                 dY:= dX;
       
   346                 fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod);
   328                 end;
   347                 end;
   329             if (Flags and 1 <> 0) and TraceDrown(x, y, Point.x, Point.y, dX, dY, erasure) then
   348             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   330                 if Score > 0 then
   349                 if Score > 0 then
   331                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
   350                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
   332                 else
   351                 else
   333                     dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
   352                     dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
   334             else if dmg >= abs(Score) then
   353             else if (dmg+fallDmg) >= abs(Score) then
   335                 if Score > 0 then
   354                 if Score > 0 then
   336                     inc(rate, KillScore)
   355                     inc(rate, KillScore)
   337                 else
   356                 else
   338                     dec(rate, KillScore * friendlyfactor div 100)
   357                     dec(rate, KillScore * friendlyfactor div 100)
   339             else
   358             else
   340                 if Score > 0 then
   359                 if Score > 0 then
   341                     inc(rate, dmg)
   360                     inc(rate, dmg+fallDmg)
   342             else
   361             else
   343                 dec(rate, dmg * friendlyfactor div 100)
   362                 dec(rate, (dmg+fallDmg) * friendlyfactor div 100)
   344             end;
   363             end;
   345         end;
   364         end;
   346 RateExplosion:= rate * 1024;
   365 RateExplosion:= rate * 1024;
   347 end;
   366 end;
   348 
   367 
   349 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
   368 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
   350 var i, dmg, rate: LongInt;
   369 var i, fallDmg, dmg, rate: LongInt;
   351     dX, dY, dmgMod: real;
   370     dX, dY, dmgMod: real;
   352 begin
   371 begin
       
   372 fallDmg:= 0;
   353 dX:= gdX * 0.005 * kick;
   373 dX:= gdX * 0.005 * kick;
   354 dY:= gdY * 0.005 * kick;
   374 dY:= gdY * 0.005 * kick;
   355 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
   375 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
   356 rate:= 0;
   376 rate:= 0;
   357 for i:= 0 to Pred(Targets.Count) do
   377 for i:= 0 to Pred(Targets.Count) do
   363             dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
   383             dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
   364             dmg:= trunc(dmg * dmgMod);
   384             dmg:= trunc(dmg * dmgMod);
   365             end;
   385             end;
   366         if dmg > 0 then
   386         if dmg > 0 then
   367             begin
   387             begin
   368             if (Flags and 1 <> 0) and TraceShoveDrown(Me, Point.x, Point.y-2, dX, dY) then
   388             if (Flags and 1 <> 0) then 
       
   389                 fallDmg:= trunc(TraceShoveFall(Me, Point.x, Point.y-2, dX, dY) * dmgMod);
       
   390             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   369                 if Score > 0 then
   391                 if Score > 0 then
   370                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
   392                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
   371                 else
   393                 else
   372                     dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
   394                     dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
   373             else if power >= abs(Score) then
   395             else if power+fallDmg >= abs(Score) then
   374                 if Score > 0 then
   396                 if Score > 0 then
   375                     inc(rate, KillScore)
   397                     inc(rate, KillScore)
   376                 else
   398                 else
   377                     dec(rate, KillScore * friendlyfactor div 100)
   399                     dec(rate, KillScore * friendlyfactor div 100)
   378             else
   400             else
   379                 if Score > 0 then
   401                 if Score > 0 then
   380                     inc(rate, power)
   402                     inc(rate, power+fallDmg)
   381                 else
   403                 else
   382                     dec(rate, power * friendlyfactor div 100)
   404                     dec(rate, (power+fallDmg) * friendlyfactor div 100)
   383             end;
   405             end;
   384         end;
   406         end;
   385 RateShove:= rate * 1024
   407 RateShove:= rate * 1024
   386 end;
   408 end;
   387 
   409 
   388 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
   410 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
   389 var i, dmg, baseDmg, rate, erasure: LongInt;
   411 var i, dmg, fallDmg, baseDmg, rate, erasure: LongInt;
   390     dX, dY, dmgMod: real;
   412     dX, dY, dmgMod: real;
   391 begin
   413 begin
   392 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
   414 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
   393 rate:= 0;
   415 rate:= 0;
   394 gdX:= gdX * 0.01;
   416 gdX:= gdX * 0.01;
   417             begin
   439             begin
   418             dX:= gdX * dmg;
   440             dX:= gdX * dmg;
   419             dY:= gdY * dmg;
   441             dY:= gdY * dmg;
   420             if dX < 0 then dX:= dX - 0.01
   442             if dX < 0 then dX:= dX - 0.01
   421             else dX:= dX + 0.01;
   443             else dX:= dX + 0.01;
   422             if TraceDrown(x, y, Point.x, Point.y, dX, dY, erasure) then
   444             fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod);
       
   445             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   423                 if Score > 0 then
   446                 if Score > 0 then
   424                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
   447                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
   425                 else
   448                 else
   426                     dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
   449                     dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
   427             else if dmg >= abs(Score) then
   450             else if (dmg+fallDmg) >= abs(Score) then
   428                 dmg := KillScore;
   451                 if Score > 0 then
   429             if Score > 0 then
   452                     inc(rate, KillScore)
   430                 inc(rate, dmg)
   453                 else
       
   454                     dec(rate, KillScore * friendlyfactor div 100)
   431             else
   455             else
   432                 dec(rate, dmg * friendlyfactor div 100);
   456                 if Score > 0 then
       
   457                     inc(rate, dmg+fallDmg)
       
   458             else
       
   459                 dec(rate, (dmg+fallDmg) * friendlyfactor div 100)
   433             end;
   460             end;
   434         end;        
   461         end;        
   435 RateShotgun:= rate * 1024;
   462 RateShotgun:= rate * 1024;
   436 end;
   463 end;
   437 
   464