hedgewars/uAIAmmoTests.pas
changeset 7439 0a494f951dcf
parent 7433 c7fff3e61d49
child 7441 5d64f59f2ca5
equal deleted inserted replaced
7358:57a508884052 7439:0a494f951dcf
    48 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    48 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    49 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    49 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    50 function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    50 function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    51 function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    51 function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    52 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    52 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
       
    53 function TestCake(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    53 
    54 
    54 type TAmmoTestProc = function (Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    55 type TAmmoTestProc = function (Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    55     TAmmoTest = record
    56     TAmmoTest = record
    56             proc: TAmmoTestProc;
    57             proc: TAmmoTestProc;
    57             flags: Longword;
    58             flags: Longword;
    82             (proc: nil;              flags: 0), // amTeleport
    83             (proc: nil;              flags: 0), // amTeleport
    83             //(proc: @TestTeleport;    flags: amtest_OnTurn), // amTeleport
    84             //(proc: @TestTeleport;    flags: amtest_OnTurn), // amTeleport
    84             (proc: nil;              flags: 0), // amSwitch
    85             (proc: nil;              flags: 0), // amSwitch
    85             (proc: @TestMortar;      flags: 0), // amMortar
    86             (proc: @TestMortar;      flags: 0), // amMortar
    86             (proc: nil;              flags: 0), // amKamikaze
    87             (proc: nil;              flags: 0), // amKamikaze
    87             (proc: nil;              flags: 0), // amCake
    88             (proc: @TestCake;        flags: amtest_OnTurn or amtest_NoTarget), // amCake
    88             (proc: nil;              flags: 0), // amSeduction
    89             (proc: nil;              flags: 0), // amSeduction
    89             (proc: @TestWatermelon;  flags: 0), // amWatermelon
    90             (proc: @TestWatermelon;  flags: 0), // amWatermelon
    90             (proc: nil;              flags: 0), // amHellishBomb
    91             (proc: nil;              flags: 0), // amHellishBomb
    91             (proc: nil;              flags: 0), // amNapalm
    92             (proc: nil;              flags: 0), // amNapalm
    92             (proc: nil;              flags: 0), // amDrill
    93             (proc: nil;              flags: 0), // amDrill
   119             );
   120             );
   120 
   121 
   121 const BadTurn = Low(LongInt) div 4;
   122 const BadTurn = Low(LongInt) div 4;
   122 
   123 
   123 implementation
   124 implementation
   124 uses uAIMisc, uVariables, uUtils;
   125 uses uAIMisc, uVariables, uUtils, uGearsHandlers, uCollisions;
   125 
   126 
   126 function Metric(x1, y1, x2, y2: LongInt): LongInt; inline;
   127 function Metric(x1, y1, x2, y2: LongInt): LongInt; inline;
   127 begin
   128 begin
   128 Metric:= abs(x1 - x2) + abs(y1 - y2)
   129 Metric:= abs(x1 - x2) + abs(y1 - y2)
   129 end;
   130 end;
   597 function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   598 function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   598 var Vx, Vy, x, y, t, dmgMod: real;
   599 var Vx, Vy, x, y, t, dmgMod: real;
   599     d: Longword;
   600     d: Longword;
   600     fallDmg, valueResult: LongInt;
   601     fallDmg, valueResult: LongInt;
   601 begin
   602 begin
       
   603 if Me^.Hedgehog^.BotLevel > 3 then exit(BadTurn);
   602 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
   604 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
   603 Level:= Level; // avoid compiler hint
   605 Level:= Level; // avoid compiler hint
   604 ap.ExplR:= 0;
   606 ap.ExplR:= 0;
   605 ap.Time:= 0;
   607 ap.Time:= 0;
   606 ap.Power:= 1;
   608 ap.Power:= 1;
   646 function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   648 function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   647 var Vx, Vy, x, y, t, dmg, dmgMod: real;
   649 var Vx, Vy, x, y, t, dmg, dmgMod: real;
   648     d: Longword;
   650     d: Longword;
   649     fallDmg, valueResult: LongInt;
   651     fallDmg, valueResult: LongInt;
   650 begin
   652 begin
       
   653 if Me^.Hedgehog^.BotLevel > 3 then exit(BadTurn);
   651 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
   654 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
   652 Level:= Level; // avoid compiler hint
   655 Level:= Level; // avoid compiler hint
   653 ap.ExplR:= 0;
   656 ap.ExplR:= 0;
   654 ap.Time:= 0;
   657 ap.Time:= 0;
   655 ap.Power:= 1;
   658 ap.Power:= 1;
   692 end;
   695 end;
   693 
   696 
   694 
   697 
   695 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   698 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   696 var valueResult, a, v1, v2: LongInt;
   699 var valueResult, a, v1, v2: LongInt;
   697     x, y: LongInt;
   700     x, y, trackFall: LongInt;
   698     dx, dy: real;
   701     dx, dy: real;
   699 begin
   702 begin
       
   703     if Me^.Hedgehog^.BotLevel < 3 then trackFall:= afTrackFall
       
   704     else trackFall:= 0;
   700     Level:= Level; // avoid compiler hint
   705     Level:= Level; // avoid compiler hint
   701     ap.ExplR:= 0;
   706     ap.ExplR:= 0;
   702     ap.Time:= 0;
   707     ap.Time:= 0;
   703     ap.Power:= 1;
   708     ap.Power:= 1;
   704     x:= hwRound(Me^.X);
   709     x:= hwRound(Me^.X);
   705     y:= hwRound(Me^.Y);
   710     y:= hwRound(Me^.Y);
   706 
   711 
   707     a:= 0;
   712     a:= cMaxAngle div 2;
   708     valueResult:= 0;
   713     valueResult:= 0;
   709 
   714 
   710     while a <= cMaxAngle div 2 do
   715     while a >= 0 do
   711         begin
   716         begin
   712         dx:= sin(a / cMaxAngle * pi) * 0.5;
   717         dx:= sin(a / cMaxAngle * pi) * 0.5;
   713         dy:= cos(a / cMaxAngle * pi) * 0.5;
   718         dy:= cos(a / cMaxAngle * pi) * 0.5;
   714 
   719 
   715         v1:= RateShove(Me, x - 10, y
   720         v1:= RateShove(Me, x - 10, y + 2
   716                 , 33, 30, 115
   721                 , 32, 30, 115
   717                 , -dx, -dy, afTrackFall);
   722                 , -dx, -dy, trackFall);
   718         v2:= RateShove(Me, x + 10, y
   723         v2:= RateShove(Me, x + 10, y + 2
   719                 , 33, 30, 115
   724                 , 32, 30, 115
   720                 , dx, -dy, afTrackFall);
   725                 , dx, -dy, trackFall);
   721         if (v1 > valueResult) or (v2 > valueResult) then
   726         if (v1 > valueResult) or (v2 > valueResult) then
   722             if (v2 > v1) 
   727             if (v2 > v1) 
   723                 or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   728                 or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   724                 begin
   729                 begin
   725                 ap.Angle:= a;
   730                 ap.Angle:= a;
   729                 begin
   734                 begin
   730                 ap.Angle:= -a;
   735                 ap.Angle:= -a;
   731                 valueResult:= v1
   736                 valueResult:= v1
   732                 end;
   737                 end;
   733 
   738 
   734         a:= a + 15 + random(cMaxAngle div 16)
   739         a:= a - 15 - random(cMaxAngle div 16)
   735         end;
   740         end;
   736    
   741    
   737     if valueResult <= 0 then
   742     if valueResult <= 0 then
   738         valueResult:= BadTurn;
   743         valueResult:= BadTurn;
   739 
   744 
   740     TestBaseballBat:= valueResult;
   745     TestBaseballBat:= valueResult;
   741 end;
   746 end;
   742 
   747 
   743 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   748 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   744 var valueResult, v1, v2, i: LongInt;
   749 var valueResult, v1, v2, i: LongInt;
   745     x, y: LongInt;
   750     x, y, trackFall: LongInt;
   746 begin
   751 begin
       
   752     if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall
       
   753     else trackFall:= 0;
       
   754     Level:= Level; // avoid compiler hint
       
   755     ap.ExplR:= 0;
       
   756     ap.Time:= 0;
       
   757     ap.Power:= 1;
       
   758     x:= hwRound(Me^.X);
       
   759     y:= hwRound(Me^.Y) + 4;
       
   760 
       
   761     v1:= 0;
       
   762     for i:= 0 to 8 do
       
   763         begin
       
   764         v1:= v1 + RateShove(Me, x - 5, y - 10 * i
       
   765                 , 19, 30, 40
       
   766                 , -0.45, -0.9, trackFall or afSetSkip);
       
   767         end;
       
   768     v1:= v1 + RateShove(Me, x - 5, y - 90
       
   769             , 19, 30, 40
       
   770             , -0.45, -0.9, trackFall);
       
   771 
       
   772 
       
   773     // now try opposite direction
       
   774     v2:= 0;
       
   775     for i:= 0 to 8 do
       
   776         begin
       
   777         v2:= v2 + RateShove(Me, x + 5, y - 10 * i
       
   778                 , 19, 30, 40
       
   779                 , 0.45, -0.9, trackFall or afSetSkip);
       
   780         end;
       
   781     v2:= v2 + RateShove(Me, x + 5, y - 90
       
   782             , 19, 30, 40
       
   783             , 0.45, -0.9, trackFall);
       
   784 
       
   785     if (v2 > v1) 
       
   786         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
       
   787         begin
       
   788         ap.Angle:= 1;
       
   789         valueResult:= v2
       
   790         end
       
   791     else 
       
   792         begin
       
   793         ap.Angle:= -1;
       
   794         valueResult:= v1
       
   795         end;
       
   796     
       
   797     if valueResult <= 0 then
       
   798         valueResult:= BadTurn;
       
   799 
       
   800     TestFirePunch:= valueResult;
       
   801 end;
       
   802 
       
   803 
       
   804 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
       
   805 var valueResult, v1, v2: LongInt;
       
   806     x, y, trackFall: LongInt;
       
   807 begin
       
   808     if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall
       
   809     else trackFall:= 0;
   747     Level:= Level; // avoid compiler hint
   810     Level:= Level; // avoid compiler hint
   748     ap.ExplR:= 0;
   811     ap.ExplR:= 0;
   749     ap.Time:= 0;
   812     ap.Time:= 0;
   750     ap.Power:= 1;
   813     ap.Power:= 1;
   751     x:= hwRound(Me^.X);
   814     x:= hwRound(Me^.X);
   752     y:= hwRound(Me^.Y);
   815     y:= hwRound(Me^.Y);
   753 
   816 
   754     v1:= 0;
       
   755     for i:= 0 to 8 do
       
   756         begin
       
   757         v1:= v1 + RateShove(Me, x - 10, y - 10 * i
       
   758                 , 18, 30, 40
       
   759                 , -0.45, -0.9, afTrackFall or afSetSkip);
       
   760         end;
       
   761     v1:= v1 + RateShove(Me, x - 10, y - 90
       
   762             , 18, 30, 40
       
   763             , -0.45, -0.9, afTrackFall);
       
   764 
       
   765 
       
   766     // now try opposite direction
       
   767     v2:= 0;
       
   768     for i:= 0 to 8 do
       
   769         begin
       
   770         v2:= v2 + RateShove(Me, x + 10, y - 10 * i
       
   771                 , 18, 30, 40
       
   772                 , 0.45, -0.9, afTrackFall or afSetSkip);
       
   773         end;
       
   774     v2:= v2 + RateShove(Me, x + 10, y - 90
       
   775             , 18, 30, 40
       
   776             , 0.45, -0.9, afTrackFall);
       
   777 
       
   778     if (v2 > v1) 
       
   779         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
       
   780         begin
       
   781         ap.Angle:= 1;
       
   782         valueResult:= v2
       
   783         end
       
   784     else 
       
   785         begin
       
   786         ap.Angle:= -1;
       
   787         valueResult:= v1
       
   788         end;
       
   789     
       
   790     if valueResult <= 0 then
       
   791         valueResult:= BadTurn;
       
   792 
       
   793     TestFirePunch:= valueResult;
       
   794 end;
       
   795 
       
   796 
       
   797 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
       
   798 var valueResult, v1, v2: LongInt;
       
   799     x, y: LongInt;
       
   800 begin
       
   801     Level:= Level; // avoid compiler hint
       
   802     ap.ExplR:= 0;
       
   803     ap.Time:= 0;
       
   804     ap.Power:= 1;
       
   805     x:= hwRound(Me^.X);
       
   806     y:= hwRound(Me^.Y);
       
   807 
       
   808     // check left direction
   817     // check left direction
   809     {first RateShove checks farthermost of two whip's AmmoShove attacks 
   818     {first RateShove checks farthermost of two whip's AmmoShove attacks 
   810     to encourage distant attacks (damaged hog is excluded from view of second 
   819     to encourage distant attacks (damaged hog is excluded from view of second 
   811     RateShove call)}
   820     RateShove call)}
   812     v1:= RateShove(Me, x - 15, y
   821     v1:= RateShove(Me, x - 13, y
   813             , 30, 30, 25
   822             , 30, 30, 25
   814             , -1, -0.8, afTrackFall or afSetSkip);
   823             , -1, -0.8, trackFall or afSetSkip);
   815     v1:= v1 +
   824     v1:= v1 +
   816         RateShove(Me, x, y
   825         RateShove(Me, x, y
   817             , 30, 30, 25
   826             , 30, 30, 25
   818             , -1, -0.8, afTrackFall);
   827             , -1, -0.8, trackFall);
   819     // now try opposite direction
   828     // now try opposite direction
   820     v2:= RateShove(Me, x + 15, y
   829     v2:= RateShove(Me, x + 13, y
   821             , 30, 30, 25
   830             , 30, 30, 25
   822             , 1, -0.8, afTrackFall or afSetSkip);
   831             , 1, -0.8, trackFall or afSetSkip);
   823     v2:= v2 +
   832     v2:= v2 +
   824         RateShove(Me, x, y
   833         RateShove(Me, x, y
   825             , 30, 30, 25
   834             , 30, 30, 25
   826             , 1, -0.8, afTrackFall);
   835             , 1, -0.8, trackFall);
   827 
   836 
   828     if (v2 > v1) 
   837     if (v2 > v1) 
   829         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   838         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   830         begin
   839         begin
   831         ap.Angle:= 1;
   840         ap.Angle:= 1;
   971             TestTeleport := 0;
   980             TestTeleport := 0;
   972             end;
   981             end;
   973         end;
   982         end;
   974 end;
   983 end;
   975 
   984 
       
   985 
       
   986 procedure checkCakeWalk(Me, Gear: PGear; var ap: TAttackParams);
       
   987 var i: Longword;
       
   988     v: LongInt;
       
   989 begin
       
   990 while (not TestColl(hwRound(Gear^.X), hwRound(Gear^.Y), 6)) and (Gear^.Y.Round < LAND_HEIGHT) do
       
   991     Gear^.Y:= Gear^.Y + _1;
       
   992 
       
   993 for i:= 0 to 2040 do
       
   994     begin
       
   995     cakeStep(Gear);
       
   996     v:= RateExplosion(Me, hwRound(Gear^.X), hwRound(Gear^.Y), cakeDmg * 2, afTrackFall);
       
   997     if v > ap.Power then 
       
   998         begin
       
   999         ap.ExplX:= hwRound(Gear^.X);
       
  1000         ap.ExplY:= hwRound(Gear^.Y);
       
  1001         ap.Power:= v
       
  1002         end
       
  1003     end;
       
  1004 end;
       
  1005 
       
  1006 function TestCake(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
       
  1007 var valueResult, v1, v2: LongInt;
       
  1008     x, y, trackFall: LongInt;
       
  1009     cake: TGear;
       
  1010 begin
       
  1011     Level:= Level; // avoid compiler hint
       
  1012     ap.ExplR:= 0;
       
  1013     ap.Time:= 0;
       
  1014     ap.Power:= BadTurn; // use it as max score value in checkCakeWalk
       
  1015 
       
  1016     FillChar(cake, sizeof(cake), 0);
       
  1017     cake.Radius:= 7;
       
  1018     cake.CollisionMask:= $FF7F;
       
  1019 
       
  1020     // check left direction
       
  1021     cake.Angle:= 3;
       
  1022     cake.dX.isNegative:= true;
       
  1023     cake.X:= Me^.X - _3;
       
  1024     cake.Y:= Me^.Y;
       
  1025     checkCakeWalk(Me, @cake, ap);
       
  1026     v1:= ap.Power;
       
  1027 
       
  1028     // now try opposite direction
       
  1029     cake.Angle:= 1;
       
  1030     cake.dX.isNegative:= false;
       
  1031     cake.X:= Me^.X + _3;
       
  1032     cake.Y:= Me^.Y;
       
  1033     checkCakeWalk(Me, @cake, ap);
       
  1034     v2:= ap.Power;
       
  1035 
       
  1036     ap.Power:= 1;
       
  1037 
       
  1038     if (v2 > v1) then
       
  1039         begin
       
  1040         ap.Angle:= 1;
       
  1041         valueResult:= v2
       
  1042         end
       
  1043     else
       
  1044         begin
       
  1045         ap.Angle:= -1;
       
  1046         valueResult:= v1
       
  1047         end;
       
  1048 
       
  1049     if valueResult <= 0 then
       
  1050         valueResult:= BadTurn;
       
  1051 
       
  1052     TestCake:= valueResult;
       
  1053 end;
       
  1054 
   976 end.
  1055 end.