559 until (rTime > 5050 - Level * 800); |
559 until (rTime > 5050 - Level * 800); |
560 TestSnowball:= valueResult |
560 TestSnowball:= valueResult |
561 end; |
561 end; |
562 |
562 |
563 function TestMolotov(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt; |
563 function TestMolotov(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt; |
564 var Vx, Vy, r: real; |
564 const timeLimit = 50; |
565 Score, EX, EY, valueResult: LongInt; |
565 var Vx, Vy, r, meX, meY: real; |
566 TestTime: LongInt; |
566 rTime: LongInt; |
567 targXWrap, x, y, dY, meX, meY: real; |
567 EX, EY: LongInt; |
|
568 valueResult: LongInt; |
|
569 targXWrap, x, y, dX, dY: real; |
568 t: LongInt; |
570 t: LongInt; |
|
571 value, range: LongInt; |
569 begin |
572 begin |
570 Flags:= Flags; // avoid compiler hint |
573 Flags:= Flags; // avoid compiler hint |
571 meX:= hwFloat2Float(Me^.X); |
574 meX:= hwFloat2Float(Me^.X); |
572 meY:= hwFloat2Float(Me^.Y); |
575 meY:= hwFloat2Float(Me^.Y); |
573 valueResult:= BadTurn; |
576 ap.Time:= 0; |
574 TestTime:= 0; |
577 rTime:= 350; |
575 ap.ExplR:= 0; |
578 ap.ExplR:= 0; |
576 if (WorldEdge = weWrap) then |
579 if (WorldEdge = weWrap) then |
577 if (Targ.Point.X < meX) then |
580 if (Targ.Point.X < meX) then |
578 targXWrap:= Targ.Point.X + (RightX-LeftX) |
581 targXWrap:= Targ.Point.X + (RightX-LeftX) |
579 else targXWrap:= Targ.Point.X - (RightX-LeftX); |
582 else targXWrap:= Targ.Point.X - (RightX-LeftX); |
|
583 valueResult:= BadTurn; |
580 repeat |
584 repeat |
581 inc(TestTime, 300); |
585 rTime:= rTime + 300 + Level * 50 + random(300); |
582 if (WorldEdge = weWrap) and (random(2)=0) then |
586 if (WorldEdge = weWrap) and (random(2)=0) then |
583 Vx:= (targXWrap - meX) / TestTime |
587 Vx:= (targXWrap + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime |
584 else Vx:= (Targ.Point.X - meX) / TestTime; |
588 else |
585 Vy:= cGravityf * (TestTime div 2) - Targ.Point.Y - meY / TestTime; |
589 Vx:= (Targ.Point.X + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime; |
|
590 Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - meY) / rTime; |
586 r:= sqr(Vx) + sqr(Vy); |
591 r:= sqr(Vx) + sqr(Vy); |
|
592 |
587 if not (r > 1) then |
593 if not (r > 1) then |
588 begin |
594 begin |
589 x:= meX; |
595 x:= meX; |
590 y:= meY; |
596 y:= meY; |
|
597 dX:= Vx; |
591 dY:= -Vy; |
598 dY:= -Vy; |
592 t:= TestTime; |
599 t:= rTime; |
593 repeat |
600 repeat |
594 x:= CheckWrap(x); |
601 x:= CheckWrap(x); |
595 x:= x + Vx; |
602 x:= x + dX; |
|
603 |
596 y:= y + dY; |
604 y:= y + dY; |
597 dY:= dY + cGravityf; |
605 dY:= dY + cGravityf; |
598 dec(t) |
606 dec(t) |
599 until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or |
607 until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or |
600 ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0); |
608 ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t < -timeLimit); |
|
609 |
601 EX:= trunc(x); |
610 EX:= trunc(x); |
602 EY:= trunc(y); |
611 EY:= trunc(y); |
603 if t < 50 then |
612 |
604 Score:= RateExplosion(Me, EX, EY, 97) // average of 17 attempts, most good, but some failing spectacularly |
613 // Sanity check 1: Make sure we're not too close to impact location |
|
614 range:= Metric(trunc(meX), trunc(meY), EX, EY); |
|
615 if (range < 150) and (Level < 5) then |
|
616 exit(BadTurn); |
|
617 |
|
618 // Sanity check 2: If impact location is close, above us and wind blows |
|
619 // towards us, there's a risk of fire flying towards us, so fail in this case. |
|
620 if (Level < 3) and (range <= 600) and (trunc(meY) >= EX) and |
|
621 (((ap.Angle < 0) and (windSpeed > 0)) or ((ap.Angle > 0) and (windSpeed < 0))) then |
|
622 exit(BadTurn); |
|
623 |
|
624 if t >= -timeLimit then |
|
625 value:= RateExplosion(Me, EX, EY, 97) // average of 17 attempts, most good, but some failing spectacularly |
605 else |
626 else |
606 Score:= BadTurn; |
627 value:= BadTurn; |
607 |
628 |
608 if valueResult < Score then |
629 if (value = 0) and (Targ.Kind = gtHedgehog) and (Targ.Score > 0) then |
|
630 value := BadTurn; |
|
631 |
|
632 if (valueResult < value) or ((valueResult = value) and (Level < 3)) then |
609 begin |
633 begin |
610 ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); |
634 ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9)); |
611 ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15); |
635 ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1); |
612 ap.ExplR:= 100; |
636 ap.ExplR:= 100; |
613 ap.ExplX:= EX; |
637 ap.ExplX:= EX; |
614 ap.ExplY:= EY; |
638 ap.ExplY:= EY; |
615 valueResult:= Score |
639 valueResult:= value |
616 end; |
640 end; |
617 end |
641 end |
618 until (TestTime > 5050 - Level * 800); |
642 until rTime > 5050 - Level * 800; |
619 TestMolotov:= valueResult |
643 TestMolotov:= valueResult |
620 end; |
644 end; |
621 |
645 |
622 function TestGrenade(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt; |
646 function TestGrenade(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt; |
623 const tDelta = 24; |
647 const tDelta = 24; |