74 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline; |
74 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline; |
75 procedure FillBonuses(isAfterAttack: boolean); |
75 procedure FillBonuses(isAfterAttack: boolean); |
76 procedure AwareOfExplosion(x, y, r: LongInt); inline; |
76 procedure AwareOfExplosion(x, y, r: LongInt); inline; |
77 |
77 |
78 function RatePlace(Gear: PGear): LongInt; |
78 function RatePlace(Gear: PGear): LongInt; |
|
79 function CheckWrap(x: real): real; inline; |
79 function TestColl(x, y, r: LongInt): boolean; inline; |
80 function TestColl(x, y, r: LongInt): boolean; inline; |
80 function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; |
81 function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; |
81 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; |
82 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; |
82 |
83 |
83 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; |
84 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; |
86 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
87 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
87 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
88 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
88 function RateHammer(Me: PGear): LongInt; |
89 function RateHammer(Me: PGear): LongInt; |
89 |
90 |
90 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; |
91 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; |
91 function AIrndSign(num: LongInt): LongInt; |
92 function AIrndSign(num: LongInt): LongInt; inline; |
|
93 function AIrndOffset(targ: TTarget; Level: LongWord): LongInt; inline; |
92 |
94 |
93 var ThinkingHH: PGear; |
95 var ThinkingHH: PGear; |
94 Targets: TTargets; |
96 Targets: TTargets; |
95 |
97 |
96 bonuses: TBonuses; |
98 bonuses: TBonuses; |
225 , gtWatermelon |
227 , gtWatermelon |
226 , gtDrill |
228 , gtDrill |
227 , gtAirBomb |
229 , gtAirBomb |
228 , gtCluster |
230 , gtCluster |
229 , gtMelonPiece |
231 , gtMelonPiece |
|
232 , gtBee |
230 , gtMolotov: bonuses.activity:= true; |
233 , gtMolotov: bonuses.activity:= true; |
231 gtCase: |
234 gtCase: |
232 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y) + 3, 37, 25); |
235 if (Gear^.AIHints and aihDoesntMatter) = 0 then |
|
236 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y) + 3, 37, 25); |
233 gtFlame: |
237 gtFlame: |
234 if (Gear^.State and gsttmpFlag) <> 0 then |
238 if (Gear^.State and gsttmpFlag) <> 0 then |
235 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 20, -50); |
239 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 20, -50); |
236 // avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow |
240 // avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow |
237 gtMine: begin |
241 gtMine: begin |
238 if (Gear^.State and gstMoving) <> 0 then bonuses.activity:= true; |
242 if (Gear^.State and gstMoving) <> 0 then bonuses.activity:= true; |
239 |
243 |
240 if ((Gear^.State and gstAttacking) = 0) and (((cMineDudPercent < 90) and (Gear^.Health <> 0)) |
244 if ((Gear^.State and gstAttacking) = 0) and (((cMineDudPercent < 90) or ((Gear^.State and gstWait) <> 0) and (Gear^.Health <> 0)) |
241 or (isAfterAttack and (Gear^.Health = 0) and (Gear^.Damage > 30))) then |
245 or (isAfterAttack and (Gear^.Health = 0) and (Gear^.Damage > 30))) then |
242 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -50) |
246 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -50) |
243 else if (Gear^.State and gstAttacking) <> 0 then |
247 else if (Gear^.State and gstAttacking) <> 0 then |
244 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, -50); // mine is on |
248 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, -50); // mine is on |
245 end; |
249 end; |
|
250 gtAirMine: if ((Gear^.State and gstFrozen) = 0) then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), gear^.Angle+5, -30); |
246 |
251 |
247 gtExplosives: |
252 gtExplosives: |
248 begin |
253 begin |
249 //if (Gear^.State and gstMoving) <> 0 then bonuses.activity:= true; |
254 //if (Gear^.State and gstMoving) <> 0 then bonuses.activity:= true; |
250 |
255 |
328 inc(rate, Score * (Radius - r)) |
333 inc(rate, Score * (Radius - r)) |
329 end; |
334 end; |
330 RatePlace:= rate; |
335 RatePlace:= rate; |
331 end; |
336 end; |
332 |
337 |
|
338 function CheckWrap(x: real): real; inline; |
|
339 begin |
|
340 if WorldEdge = weWrap then |
|
341 if (x < leftX) then |
|
342 x:= x + (rightX - leftX) |
|
343 else if x > rightX then |
|
344 x:= x - (rightX - leftX); |
|
345 CheckWrap:= x; |
|
346 end; |
|
347 |
333 function CheckBounds(x, y, r: Longint): boolean; inline; |
348 function CheckBounds(x, y, r: Longint): boolean; inline; |
334 begin |
349 begin |
335 CheckBounds := (((x-r) and LAND_WIDTH_MASK) = 0) and |
350 CheckBounds := (((x-r) and LAND_WIDTH_MASK) = 0) and |
336 (((x+r) and LAND_WIDTH_MASK) = 0) and |
351 (((x+r) and LAND_WIDTH_MASK) = 0) and |
337 (((y-r) and LAND_HEIGHT_MASK) = 0) and |
352 (((y-r) and LAND_HEIGHT_MASK) = 0) and |
370 function TestColl(x, y, r: LongInt): boolean; inline; |
385 function TestColl(x, y, r: LongInt): boolean; inline; |
371 begin |
386 begin |
372 if not CheckBounds(x, y, r) then |
387 if not CheckBounds(x, y, r) then |
373 exit(false); |
388 exit(false); |
374 |
389 |
375 if (Land[y-r, x-r] and lfNotCurrentMask <> 0) or |
390 if (Land[y-r, x-r] and lfNotCurHogCrate <> 0) or |
376 (Land[y+r, x-r] and lfNotCurrentMask <> 0) or |
391 (Land[y+r, x-r] and lfNotCurHogCrate <> 0) or |
377 (Land[y+r, x-r] and lfNotCurrentMask <> 0) or |
392 (Land[y+r, x-r] and lfNotCurHogCrate <> 0) or |
378 (Land[y+r, x+r] and lfNotCurrentMask <> 0) then |
393 (Land[y+r, x+r] and lfNotCurHogCrate <> 0) then |
379 exit(true); |
394 exit(true); |
380 |
395 |
381 TestColl:= false; |
396 TestColl:= false; |
382 end; |
397 end; |
383 |
398 |
410 skipLandCheck:= true; |
425 skipLandCheck:= true; |
411 // ok. attempt approximate search for an unbroken trajectory into water. if it continues far enough, assume out of map |
426 // ok. attempt approximate search for an unbroken trajectory into water. if it continues far enough, assume out of map |
412 rCorner:= r * 0.75; |
427 rCorner:= r * 0.75; |
413 while true do |
428 while true do |
414 begin |
429 begin |
|
430 x:= CheckWrap(x); |
415 x:= x + dX; |
431 x:= x + dX; |
416 y:= y + dY; |
432 y:= y + dY; |
417 dY:= dY + cGravityf; |
433 dY:= dY + cGravityf; |
418 skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner)); |
434 skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner)); |
419 if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then |
435 if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then |
517 function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
534 function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
518 var i, fallDmg, dmg, dmgBase, rate, subrate, erasure: LongInt; |
535 var i, fallDmg, dmg, dmgBase, rate, subrate, erasure: LongInt; |
519 pX, pY, dX, dY: real; |
536 pX, pY, dX, dY: real; |
520 hadSkips: boolean; |
537 hadSkips: boolean; |
521 begin |
538 begin |
|
539 x:= round(CheckWrap(real(x))); |
522 fallDmg:= 0; |
540 fallDmg:= 0; |
523 rate:= 0; |
541 rate:= 0; |
524 // add our virtual position |
542 // add our virtual position |
525 with Targets.ar[Targets.Count] do |
543 with Targets.ar[Targets.Count] do |
526 begin |
544 begin |
613 if abs(subrate) > 2000 then inc(Rate,subrate); |
631 if abs(subrate) > 2000 then inc(Rate,subrate); |
614 end |
632 end |
615 end |
633 end |
616 end; |
634 end; |
617 |
635 |
618 if hadSkips and (rate = 0) then |
636 if hadSkips and (rate <= 0) then |
619 RealRateExplosion:= BadTurn |
637 RealRateExplosion:= BadTurn |
620 else |
638 else |
621 RealRateExplosion:= rate; |
639 RealRateExplosion:= rate; |
622 end; |
640 end; |
623 |
641 |
624 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
642 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
625 var i, fallDmg, dmg, rate, subrate: LongInt; |
643 var i, fallDmg, dmg, rate, subrate: LongInt; |
626 dX, dY, pX, pY: real; |
644 dX, dY, pX, pY: real; |
|
645 hadSkips: boolean; |
627 begin |
646 begin |
628 fallDmg:= 0; |
647 fallDmg:= 0; |
629 dX:= gdX * 0.01 * kick; |
648 dX:= gdX * 0.01 * kick; |
630 dY:= gdY * 0.01 * kick; |
649 dY:= gdY * 0.01 * kick; |
631 rate:= 0; |
650 rate:= 0; |
|
651 hadSkips:= false; |
632 for i:= 0 to Pred(Targets.Count) do |
652 for i:= 0 to Pred(Targets.Count) do |
633 with Targets.ar[i] do |
653 with Targets.ar[i] do |
634 if skip then |
654 if skip then |
635 begin |
655 begin |
636 if Flags and afSetSkip = 0 then skip:= false |
656 if Flags and afSetSkip = 0 then skip:= false |
693 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) |
713 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) |
694 else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall)); |
714 else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall)); |
695 if abs(subrate) > 2000 then inc(Rate,subrate div 1024); |
715 if abs(subrate) > 2000 then inc(Rate,subrate div 1024); |
696 end |
716 end |
697 end |
717 end |
698 end; |
718 end |
699 RateShove:= rate * 1024; |
719 else |
|
720 hadSkips:= true; |
|
721 |
|
722 if hadSkips and (rate <= 0) then |
|
723 RateShove:= BadTurn |
|
724 else |
|
725 RateShove:= rate * 1024; |
700 ResetTargets |
726 ResetTargets |
701 end; |
727 end; |
702 |
728 |
703 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
729 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
704 var i, dmg, fallDmg, baseDmg, rate, subrate, erasure: LongInt; |
730 var i, dmg, fallDmg, baseDmg, rate, subrate, erasure: LongInt; |
797 if abs(subrate) > 2000 then inc(Rate,subrate div 1024); |
823 if abs(subrate) > 2000 then inc(Rate,subrate div 1024); |
798 end |
824 end |
799 end |
825 end |
800 end; |
826 end; |
801 |
827 |
802 if hadSkips and (rate = 0) then |
828 if hadSkips and (rate <= 0) then |
803 RateShotgun:= BadTurn |
829 RateShotgun:= BadTurn |
804 else |
830 else |
805 RateShotgun:= rate * 1024; |
831 RateShotgun:= rate * 1024; |
806 ResetTargets; |
832 ResetTargets; |
807 end; |
833 end; |
808 |
834 |
809 function RateHammer(Me: PGear): LongInt; |
835 function RateHammer(Me: PGear): LongInt; |
810 var x, y, i, r, rate: LongInt; |
836 var x, y, i, r, rate: LongInt; |
|
837 hadSkips: boolean; |
811 begin |
838 begin |
812 // hammer hit shift against attecker hog is 10 |
839 // hammer hit shift against attecker hog is 10 |
813 x:= hwRound(Me^.X) + hwSign(Me^.dX) * 10; |
840 x:= hwRound(Me^.X) + hwSign(Me^.dX) * 10; |
814 y:= hwRound(Me^.Y); |
841 y:= hwRound(Me^.Y); |
815 rate:= 0; |
842 rate:= 0; |
816 |
843 hadSkips:= false; |
817 for i:= 0 to Pred(Targets.Count) do |
844 for i:= 0 to Pred(Targets.Count) do |
818 with Targets.ar[i] do |
845 with Targets.ar[i] do |
819 // hammer hit radius is 8, shift is 10 |
846 // hammer hit radius is 8, shift is 10 |
820 if matters and (Kind = gtHedgehog) and (abs(Point.x - x) + abs(Point.y - y) < 18) then |
847 if (not matters) then |
|
848 hadSkips:= true |
|
849 else if matters and (Kind = gtHedgehog) and (abs(Point.x - x) + abs(Point.y - y) < 18) then |
821 begin |
850 begin |
822 r:= trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); |
851 r:= trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); |
823 |
852 |
824 if r <= 18 then |
853 if r <= 18 then |
825 if Score > 0 then |
854 if Score > 0 then |
826 inc(rate, Score div 3) |
855 inc(rate, Score div 3) |
827 else |
856 else |
828 inc(rate, Score div 3 * friendlyfactor div 100) |
857 inc(rate, Score div 3 * friendlyfactor div 100) |
829 end; |
858 end; |
830 RateHammer:= rate * 1024; |
859 |
|
860 if hadSkips and (rate <= 0) then |
|
861 RateHammer:= BadTurn |
|
862 else |
|
863 RateHammer:= rate * 1024; |
831 end; |
864 end; |
832 |
865 |
833 function HHJump(Gear: PGear; JumpType: TJumpType; var GoInfo: TGoInfo): boolean; |
866 function HHJump(Gear: PGear; JumpType: TJumpType; var GoInfo: TGoInfo): boolean; |
834 var bX, bY: LongInt; |
867 var bX, bY: LongInt; |
835 begin |
868 begin |
925 |
958 |
926 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; |
959 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; |
927 var pX, pY, tY: LongInt; |
960 var pX, pY, tY: LongInt; |
928 begin |
961 begin |
929 HHGo:= false; |
962 HHGo:= false; |
930 Gear^.CollisionMask:= lfNotCurrentMask; |
963 Gear^.CollisionMask:= lfNotCurHogCrate; |
931 AltGear^:= Gear^; |
964 AltGear^:= Gear^; |
932 |
965 |
933 GoInfo.Ticks:= 0; |
966 GoInfo.Ticks:= 0; |
934 GoInfo.FallPix:= 0; |
967 GoInfo.FallPix:= 0; |
935 GoInfo.JumpType:= jmpNone; |
968 GoInfo.JumpType:= jmpNone; |
997 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0); |
1030 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0); |
998 |
1031 |
999 HHJump(AltGear, jmpHJump, GoInfo); |
1032 HHJump(AltGear, jmpHJump, GoInfo); |
1000 end; |
1033 end; |
1001 |
1034 |
1002 function AIrndSign(num: LongInt): LongInt; |
1035 function AIrndSign(num: LongInt): LongInt; inline; |
1003 begin |
1036 begin |
1004 if random(2) = 0 then |
1037 if random(2) = 0 then |
1005 AIrndSign:= num |
1038 AIrndSign:= num |
1006 else |
1039 else |
1007 AIrndSign:= - num |
1040 AIrndSign:= - num |
1008 end; |
1041 end; |
1009 |
1042 |
|
1043 function AIrndOffset(targ: TTarget; Level: LongWord): LongInt; inline; |
|
1044 begin |
|
1045 if Level <> 1 then exit(0); |
|
1046 // at present level 2 doesn't track falls on most things |
|
1047 //if Level = 2 then exit(round(targ.Radius*(random(5)-2)/2)); |
|
1048 AIrndOffset := targ.Radius*(random(7)-3)*2 |
|
1049 end; |
|
1050 |
1010 procedure initModule; |
1051 procedure initModule; |
1011 begin |
1052 begin |
1012 friendlyfactor:= 300; |
1053 friendlyfactor:= 300; |
1013 KnownExplosion.X:= 0; |
1054 KnownExplosion.X:= 0; |
1014 KnownExplosion.Y:= 0; |
1055 KnownExplosion.Y:= 0; |