hedgewars/uAIAmmoTests.pas
changeset 7442 9bb6abdb5675
parent 7433 c7fff3e61d49
child 7441 5d64f59f2ca5
equal deleted inserted replaced
7392:bc3306c59a08 7442:9bb6abdb5675
    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;
   706     ap.Time:= 0;
   707     ap.Time:= 0;
   707     ap.Power:= 1;
   708     ap.Power:= 1;
   708     x:= hwRound(Me^.X);
   709     x:= hwRound(Me^.X);
   709     y:= hwRound(Me^.Y);
   710     y:= hwRound(Me^.Y);
   710 
   711 
   711     a:= 0;
   712     a:= cMaxAngle div 2;
   712     valueResult:= 0;
   713     valueResult:= 0;
   713 
   714 
   714     while a <= cMaxAngle div 2 do
   715     while a >= 0 do
   715         begin
   716         begin
   716         dx:= sin(a / cMaxAngle * pi) * 0.5;
   717         dx:= sin(a / cMaxAngle * pi) * 0.5;
   717         dy:= cos(a / cMaxAngle * pi) * 0.5;
   718         dy:= cos(a / cMaxAngle * pi) * 0.5;
   718 
   719 
   719         v1:= RateShove(Me, x - 10, y
   720         v1:= RateShove(Me, x - 10, y + 2
   720                 , 33, 30, 115
   721                 , 32, 30, 115
   721                 , -dx, -dy, trackFall);
   722                 , -dx, -dy, trackFall);
   722         v2:= RateShove(Me, x + 10, y
   723         v2:= RateShove(Me, x + 10, y + 2
   723                 , 33, 30, 115
   724                 , 32, 30, 115
   724                 , dx, -dy, trackFall);
   725                 , dx, -dy, trackFall);
   725         if (v1 > valueResult) or (v2 > valueResult) then
   726         if (v1 > valueResult) or (v2 > valueResult) then
   726             if (v2 > v1) 
   727             if (v2 > v1) 
   727                 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
   728                 begin
   729                 begin
   733                 begin
   734                 begin
   734                 ap.Angle:= -a;
   735                 ap.Angle:= -a;
   735                 valueResult:= v1
   736                 valueResult:= v1
   736                 end;
   737                 end;
   737 
   738 
   738         a:= a + 15 + random(cMaxAngle div 16)
   739         a:= a - 15 - random(cMaxAngle div 16)
   739         end;
   740         end;
   740    
   741    
   741     if valueResult <= 0 then
   742     if valueResult <= 0 then
   742         valueResult:= BadTurn;
   743         valueResult:= BadTurn;
   743 
   744 
   744     TestBaseballBat:= valueResult;
   745     TestBaseballBat:= valueResult;
   745 end;
   746 end;
   746 
   747 
   747 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;
   748 var valueResult, v1, v2, i: LongInt;
   749 var valueResult, v1, v2, i: LongInt;
       
   750     x, y, trackFall: LongInt;
       
   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;
   749     x, y, trackFall: LongInt;
   806     x, y, trackFall: LongInt;
   750 begin
   807 begin
   751     if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall
   808     if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall
   752     else trackFall:= 0;
   809     else trackFall:= 0;
   753     Level:= Level; // avoid compiler hint
   810     Level:= Level; // avoid compiler hint
   755     ap.Time:= 0;
   812     ap.Time:= 0;
   756     ap.Power:= 1;
   813     ap.Power:= 1;
   757     x:= hwRound(Me^.X);
   814     x:= hwRound(Me^.X);
   758     y:= hwRound(Me^.Y);
   815     y:= hwRound(Me^.Y);
   759 
   816 
   760     v1:= 0;
       
   761     for i:= 0 to 8 do
       
   762         begin
       
   763         v1:= v1 + RateShove(Me, x - 10, y - 10 * i
       
   764                 , 18, 30, 40
       
   765                 , -0.45, -0.9, trackFall or afSetSkip);
       
   766         end;
       
   767     v1:= v1 + RateShove(Me, x - 10, y - 90
       
   768             , 18, 30, 40
       
   769             , -0.45, -0.9, trackFall);
       
   770 
       
   771 
       
   772     // now try opposite direction
       
   773     v2:= 0;
       
   774     for i:= 0 to 8 do
       
   775         begin
       
   776         v2:= v2 + RateShove(Me, x + 10, y - 10 * i
       
   777                 , 18, 30, 40
       
   778                 , 0.45, -0.9, trackFall or afSetSkip);
       
   779         end;
       
   780     v2:= v2 + RateShove(Me, x + 10, y - 90
       
   781             , 18, 30, 40
       
   782             , 0.45, -0.9, trackFall);
       
   783 
       
   784     if (v2 > v1) 
       
   785         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
       
   786         begin
       
   787         ap.Angle:= 1;
       
   788         valueResult:= v2
       
   789         end
       
   790     else 
       
   791         begin
       
   792         ap.Angle:= -1;
       
   793         valueResult:= v1
       
   794         end;
       
   795     
       
   796     if valueResult <= 0 then
       
   797         valueResult:= BadTurn;
       
   798 
       
   799     TestFirePunch:= valueResult;
       
   800 end;
       
   801 
       
   802 
       
   803 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
       
   804 var valueResult, v1, v2: LongInt;
       
   805     x, y, trackFall: LongInt;
       
   806 begin
       
   807     if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall
       
   808     else trackFall:= 0;
       
   809     Level:= Level; // avoid compiler hint
       
   810     ap.ExplR:= 0;
       
   811     ap.Time:= 0;
       
   812     ap.Power:= 1;
       
   813     x:= hwRound(Me^.X);
       
   814     y:= hwRound(Me^.Y);
       
   815 
       
   816     // check left direction
   817     // check left direction
   817     {first RateShove checks farthermost of two whip's AmmoShove attacks 
   818     {first RateShove checks farthermost of two whip's AmmoShove attacks 
   818     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 
   819     RateShove call)}
   820     RateShove call)}
   820     v1:= RateShove(Me, x - 15, y
   821     v1:= RateShove(Me, x - 13, y
   821             , 30, 30, 25
   822             , 30, 30, 25
   822             , -1, -0.8, trackFall or afSetSkip);
   823             , -1, -0.8, trackFall or afSetSkip);
   823     v1:= v1 +
   824     v1:= v1 +
   824         RateShove(Me, x, y
   825         RateShove(Me, x, y
   825             , 30, 30, 25
   826             , 30, 30, 25
   826             , -1, -0.8, trackFall);
   827             , -1, -0.8, trackFall);
   827     // now try opposite direction
   828     // now try opposite direction
   828     v2:= RateShove(Me, x + 15, y
   829     v2:= RateShove(Me, x + 13, y
   829             , 30, 30, 25
   830             , 30, 30, 25
   830             , 1, -0.8, trackFall or afSetSkip);
   831             , 1, -0.8, trackFall or afSetSkip);
   831     v2:= v2 +
   832     v2:= v2 +
   832         RateShove(Me, x, y
   833         RateShove(Me, x, y
   833             , 30, 30, 25
   834             , 30, 30, 25
   979             TestTeleport := 0;
   980             TestTeleport := 0;
   980             end;
   981             end;
   981         end;
   982         end;
   982 end;
   983 end;
   983 
   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 
   984 end.
  1055 end.