hedgewars/uAIMisc.pas
changeset 8933 19be64b0f36e
parent 8924 13ac59499066
child 8939 b26aaf28c920
equal deleted inserted replaced
8925:f52c6f9800ca 8933:19be64b0f36e
    92 var dmgMod: real = 1.0;
    92 var dmgMod: real = 1.0;
    93 
    93 
    94 implementation
    94 implementation
    95 uses uCollisions, uVariables, uUtils, uLandTexture, uGearsUtils;
    95 uses uCollisions, uVariables, uUtils, uLandTexture, uGearsUtils;
    96 
    96 
    97 var 
    97 var
    98     KnownExplosion: record
    98     KnownExplosion: record
    99         X, Y, Radius: LongInt
    99         X, Y, Radius: LongInt
   100         end = (X: 0; Y: 0; Radius: 0);
   100         end = (X: 0; Y: 0; Radius: 0);
   101 
   101 
   102 procedure FillTargets;
   102 procedure FillTargets;
   111         if not hasGone then
   111         if not hasGone then
   112             begin
   112             begin
   113             for i:= 0 to cMaxHHIndex do
   113             for i:= 0 to cMaxHHIndex do
   114                 if (Hedgehogs[i].Gear <> nil)
   114                 if (Hedgehogs[i].Gear <> nil)
   115                 and (Hedgehogs[i].Gear <> ThinkingHH)
   115                 and (Hedgehogs[i].Gear <> ThinkingHH)
   116                 and (Hedgehogs[i].Gear^.Health > Hedgehogs[i].Gear^.Damage) 
   116                 and (Hedgehogs[i].Gear^.Health > Hedgehogs[i].Gear^.Damage)
   117                     then
   117                     then
   118                     begin
   118                     begin
   119                     with Targets.ar[Targets.Count], Hedgehogs[i] do
   119                     with Targets.ar[Targets.Count], Hedgehogs[i] do
   120                         begin
   120                         begin
   121                         skip:= false;
   121                         skip:= false;
   122                         matters:= (Hedgehogs[i].Gear^.AIHints and aihDoesntMatter) = 0;
   122                         matters:= (Hedgehogs[i].Gear^.AIHints and aihDoesntMatter) = 0;
   123                         
   123 
   124                         Point.X:= hwRound(Gear^.X);
   124                         Point.X:= hwRound(Gear^.X);
   125                         Point.Y:= hwRound(Gear^.Y);
   125                         Point.Y:= hwRound(Gear^.Y);
   126                         if Clan <> CurrentTeam^.Clan then
   126                         if Clan <> CurrentTeam^.Clan then
   127                             begin
   127                             begin
   128                             Score:= Gear^.Health - Gear^.Damage;
   128                             Score:= Gear^.Health - Gear^.Damage;
   179             gtCase:
   179             gtCase:
   180                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y) + 3, 37, 25);
   180                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y) + 3, 37, 25);
   181             gtFlame:
   181             gtFlame:
   182                 if (Gear^.State and gsttmpFlag) <> 0 then
   182                 if (Gear^.State and gsttmpFlag) <> 0 then
   183                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 20, -50);
   183                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 20, -50);
   184 // avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow 
   184 // avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow
   185             gtMine:
   185             gtMine:
   186                 if ((Gear^.State and gstAttacking) = 0) and (((cMineDudPercent < 90) and (Gear^.Health <> 0))
   186                 if ((Gear^.State and gstAttacking) = 0) and (((cMineDudPercent < 90) and (Gear^.Health <> 0))
   187                 or (isAfterAttack and (Gear^.Health = 0) and (Gear^.Damage > 30))) then
   187                 or (isAfterAttack and (Gear^.Health = 0) and (Gear^.Damage > 30))) then
   188                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -50)
   188                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -50)
   189                 else if (Gear^.State and gstAttacking) <> 0 then
   189                 else if (Gear^.State and gstAttacking) <> 0 then
   190                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, -50); // mine is on
   190                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, -50); // mine is on
   191                     
   191 
   192             gtExplosives:
   192             gtExplosives:
   193             if isAfterAttack then
   193             if isAfterAttack then
   194                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 75, -60 + Gear^.Health);
   194                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 75, -60 + Gear^.Health);
   195                 
   195 
   196             gtSMine:
   196             gtSMine:
   197                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -30);
   197                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -30);
   198                 
   198 
   199             gtDynamite:
   199             gtDynamite:
   200                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -75);
   200                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -75);
   201                 
   201 
   202             gtHedgehog:
   202             gtHedgehog:
   203                 begin
   203                 begin
   204                 if Gear^.Damage >= Gear^.Health then
   204                 if Gear^.Damage >= Gear^.Health then
   205                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 60, -25)
   205                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 60, -25)
   206                 else
   206                 else
   268 function TestCollWithEverything(x, y, r: LongInt): boolean; inline;
   268 function TestCollWithEverything(x, y, r: LongInt): boolean; inline;
   269 begin
   269 begin
   270     if not CheckBounds(x, y, r) then
   270     if not CheckBounds(x, y, r) then
   271         exit(false);
   271         exit(false);
   272 
   272 
   273     if (Land[y-r, x-r] <> 0) or    
   273     if (Land[y-r, x-r] <> 0) or
   274        (Land[y+r, x-r] <> 0) or 
   274        (Land[y+r, x-r] <> 0) or
   275        (Land[y-r, x+r] <> 0) or
   275        (Land[y-r, x+r] <> 0) or
   276        (Land[y+r, x+r] <> 0) then
   276        (Land[y+r, x+r] <> 0) then
   277        exit(true);
   277        exit(true);
   278 
   278 
   279     TestCollWithEverything := false;
   279     TestCollWithEverything := false;
   283 begin
   283 begin
   284     if not CheckBounds(x, y, r) then
   284     if not CheckBounds(x, y, r) then
   285         exit(false);
   285         exit(false);
   286 
   286 
   287     if (Land[y-r, x-r] > lfAllObjMask) or
   287     if (Land[y-r, x-r] > lfAllObjMask) or
   288        (Land[y+r, x-r] > lfAllObjMask) or 
   288        (Land[y+r, x-r] > lfAllObjMask) or
   289        (Land[y-r, x+r] > lfAllObjMask) or
   289        (Land[y-r, x+r] > lfAllObjMask) or
   290        (Land[y+r, x+r] > lfAllObjMask) then
   290        (Land[y+r, x+r] > lfAllObjMask) then
   291        exit(true);
   291        exit(true);
   292 
   292 
   293     TestCollExcludingObjects:= false;
   293     TestCollExcludingObjects:= false;
   297 begin
   297 begin
   298     if not CheckBounds(x, y, r) then
   298     if not CheckBounds(x, y, r) then
   299         exit(false);
   299         exit(false);
   300 
   300 
   301     if (Land[y-r, x-r] and lfNotCurrentMask <> 0) or
   301     if (Land[y-r, x-r] and lfNotCurrentMask <> 0) or
   302        (Land[y+r, x-r] and lfNotCurrentMask <> 0) or 
   302        (Land[y+r, x-r] and lfNotCurrentMask <> 0) or
   303        (Land[y-r, x+r] and lfNotCurrentMask <> 0) or
   303        (Land[y-r, x+r] and lfNotCurrentMask <> 0) or
   304        (Land[y+r, x+r] and lfNotCurrentMask <> 0) then
   304        (Land[y+r, x+r] and lfNotCurrentMask <> 0) then
   305        exit(true);
   305        exit(true);
   306     
   306 
   307     TestColl:= false;
   307     TestColl:= false;
   308 end;
   308 end;
   309 
   309 
   310 
   310 
   311 // Wrapper to test various approaches.  If it works reasonably, will just replace.
   311 // Wrapper to test various approaches.  If it works reasonably, will just replace.
   365     begin
   365     begin
   366         x:= x + dX;
   366         x:= x + dX;
   367         y:= y + dY;
   367         y:= y + dY;
   368         dY:= dY + cGravityf;
   368         dY:= dY + cGravityf;
   369 
   369 
   370 {        if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then 
   370 {        if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then
   371             begin
   371             begin
   372             LandPixels[trunc(y), trunc(x)]:= v;
   372             LandPixels[trunc(y), trunc(x)]:= v;
   373             UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true);
   373             UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true);
   374             end;}
   374             end;}
   375 
   375 
   433             begin
   433             begin
   434             if (Flags and afTrackFall <> 0) and (dmg < abs(Score)) then
   434             if (Flags and afTrackFall <> 0) and (dmg < abs(Score)) then
   435                 begin
   435                 begin
   436                 dX:= 0.005 * dmg + 0.01;
   436                 dX:= 0.005 * dmg + 0.01;
   437                 dY:= dX;
   437                 dY:= dX;
   438                 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and 
   438                 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
   439                    (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
   439                    (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
   440                      fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod)
   440                      fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod)
   441                 else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod)
   441                 else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod)
   442                 end;
   442                 end;
   443             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   443             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   471 dX:= gdX * 0.01 * kick;
   471 dX:= gdX * 0.01 * kick;
   472 dY:= gdY * 0.01 * kick;
   472 dY:= gdY * 0.01 * kick;
   473 rate:= 0;
   473 rate:= 0;
   474 for i:= 0 to Pred(Targets.Count) do
   474 for i:= 0 to Pred(Targets.Count) do
   475     with Targets.ar[i] do
   475     with Targets.ar[i] do
   476       if skip then 
   476       if skip then
   477         if (Flags and afSetSkip = 0) then skip:= false else {still skip}
   477         if (Flags and afSetSkip = 0) then skip:= false else {still skip}
   478       else if matters then
   478       else if matters then
   479         begin
   479         begin
   480         dmg:= 0;
   480         dmg:= 0;
   481         if abs(Point.x - x) + abs(Point.y - y) < r then
   481         if abs(Point.x - x) + abs(Point.y - y) < r then
   482             dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
   482             dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
   483 
   483 
   484         if dmg > 0 then
   484         if dmg > 0 then
   485             begin
   485             begin
   486             if (Flags and afSetSkip <> 0) then skip:= true;
   486             if (Flags and afSetSkip <> 0) then skip:= true;
   487             if (Flags and afTrackFall <> 0) and (Score > 0) then 
   487             if (Flags and afTrackFall <> 0) and (Score > 0) then
   488                 fallDmg:= trunc(TraceShoveFall(Point.x, Point.y - 2, dX, dY) * dmgMod);
   488                 fallDmg:= trunc(TraceShoveFall(Point.x, Point.y - 2, dX, dY) * dmgMod);
   489             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   489             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   490                 if Score > 0 then
   490                 if Score > 0 then
   491                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
   491                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
   492                 else
   492                 else
   546             begin
   546             begin
   547             dX:= gdX * dmg;
   547             dX:= gdX * dmg;
   548             dY:= gdY * dmg;
   548             dY:= gdY * dmg;
   549             if dX < 0 then dX:= dX - 0.01
   549             if dX < 0 then dX:= dX - 0.01
   550             else dX:= dX + 0.01;
   550             else dX:= dX + 0.01;
   551             if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and 
   551             if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
   552                (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
   552                (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
   553                  fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod)
   553                  fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod)
   554             else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod);
   554             else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod);
   555             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   555             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
   556                 if Score > 0 then
   556                 if Score > 0 then
   591         if abs(Point.x - x) + abs(Point.y - y) < 18 then
   591         if abs(Point.x - x) + abs(Point.y - y) < 18 then
   592             begin
   592             begin
   593             r:= trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
   593             r:= trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
   594 
   594 
   595             if r <= 18 then
   595             if r <= 18 then
   596                 if Score > 0 then 
   596                 if Score > 0 then
   597                     inc(rate, Score div 3)
   597                     inc(rate, Score div 3)
   598                 else
   598                 else
   599                     inc(rate, Score div 3 * friendlyfactor div 100)
   599                     inc(rate, Score div 3 * friendlyfactor div 100)
   600             end;
   600             end;
   601 RateHammer:= rate * 1024;
   601 RateHammer:= rate * 1024;
   609 GoInfo.JumpType:= jmpNone;
   609 GoInfo.JumpType:= jmpNone;
   610 bX:= hwRound(Gear^.X);
   610 bX:= hwRound(Gear^.X);
   611 bY:= hwRound(Gear^.Y);
   611 bY:= hwRound(Gear^.Y);
   612 case JumpType of
   612 case JumpType of
   613     jmpNone: exit(false);
   613     jmpNone: exit(false);
   614     
   614 
   615     jmpHJump:
   615     jmpHJump:
   616         if TestCollisionYwithGear(Gear, -1) = 0 then
   616         if TestCollisionYwithGear(Gear, -1) = 0 then
   617         begin
   617         begin
   618             Gear^.dY:= -_0_2;
   618             Gear^.dY:= -_0_2;
   619             SetLittle(Gear^.dX);
   619             SetLittle(Gear^.dX);
   620             Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
   620             Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
   621         end
   621         end
   622     else
   622     else
   623         exit(false);
   623         exit(false);
   624         
   624 
   625     jmpLJump:
   625     jmpLJump:
   626         begin
   626         begin
   627             if TestCollisionYwithGear(Gear, -1) <> 0 then
   627             if TestCollisionYwithGear(Gear, -1) <> 0 then
   628                 if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
   628                 if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
   629                     Gear^.Y:= Gear^.Y - int2hwFloat(2)
   629                     Gear^.Y:= Gear^.Y - int2hwFloat(2)
   641             exit(false)
   641             exit(false)
   642         end
   642         end
   643 end;
   643 end;
   644 
   644 
   645 repeat
   645 repeat
   646         {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then 
   646         {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then
   647             begin
   647             begin
   648             LandPixels[hwRound(Gear^.Y), hwRound(Gear^.X)]:= Gear^.Hedgehog^.Team^.Clan^.Color;
   648             LandPixels[hwRound(Gear^.Y), hwRound(Gear^.X)]:= Gear^.Hedgehog^.Team^.Clan^.Color;
   649             UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true);
   649             UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true);
   650             end;}
   650             end;}
   651             
   651 
   652     if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then
   652     if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then
   653         exit(false);
   653         exit(false);
   654     if (Gear^.State and gstMoving) <> 0 then
   654     if (Gear^.State and gstMoving) <> 0 then
   655     begin
   655     begin
   656         if (GoInfo.Ticks = 350) then
   656         if (GoInfo.Ticks = 350) then
   704 GoInfo.Ticks:= 0;
   704 GoInfo.Ticks:= 0;
   705 GoInfo.FallPix:= 0;
   705 GoInfo.FallPix:= 0;
   706 GoInfo.JumpType:= jmpNone;
   706 GoInfo.JumpType:= jmpNone;
   707 tY:= hwRound(Gear^.Y);
   707 tY:= hwRound(Gear^.Y);
   708 repeat
   708 repeat
   709         {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then 
   709         {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then
   710             begin
   710             begin
   711             LandPixels[hwRound(Gear^.Y), hwRound(Gear^.X)]:= random($FFFFFFFF);//Gear^.Hedgehog^.Team^.Clan^.Color;
   711             LandPixels[hwRound(Gear^.Y), hwRound(Gear^.X)]:= random($FFFFFFFF);//Gear^.Hedgehog^.Team^.Clan^.Color;
   712             UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true);
   712             UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true);
   713             end;}
   713             end;}
   714 
   714 
   718         begin
   718         begin
   719         if AltGear^.Hedgehog^.BotLevel < 4 then
   719         if AltGear^.Hedgehog^.BotLevel < 4 then
   720             AddWalkBonus(pX, tY, 250, -40);
   720             AddWalkBonus(pX, tY, 250, -40);
   721         exit(false)
   721         exit(false)
   722         end;
   722         end;
   723         
   723 
   724     // hog is falling    
   724     // hog is falling
   725     if (Gear^.State and gstMoving) <> 0 then
   725     if (Gear^.State and gstMoving) <> 0 then
   726         begin
   726         begin
   727         inc(GoInfo.Ticks);
   727         inc(GoInfo.Ticks);
   728         Gear^.dY:= Gear^.dY + cGravity;
   728         Gear^.dY:= Gear^.dY + cGravity;
   729         if Gear^.dY > _0_4 then
   729         if Gear^.dY > _0_4 then
   730             begin
   730             begin
   731             GoInfo.FallPix:= 0;
   731             GoInfo.FallPix:= 0;
   732             // try ljump instead of fall with damage
   732             // try ljump instead of fall with damage
   733             HHJump(AltGear, jmpLJump, GoInfo); 
   733             HHJump(AltGear, jmpLJump, GoInfo);
   734             if AltGear^.Hedgehog^.BotLevel < 4 then
   734             if AltGear^.Hedgehog^.BotLevel < 4 then
   735                 AddWalkBonus(pX, tY, 175, -20);
   735                 AddWalkBonus(pX, tY, 175, -20);
   736             exit(false)
   736             exit(false)
   737             end;
   737             end;
   738         Gear^.Y:= Gear^.Y + Gear^.dY;
   738         Gear^.Y:= Gear^.Y + Gear^.dY;