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. |