68 function TraceShoveFall(x, y, dX, dY: Real): LongInt; |
69 function TraceShoveFall(x, y, dX, dY: Real): LongInt; |
69 |
70 |
70 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; |
71 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; |
71 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline; |
72 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline; |
72 function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
73 function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
73 function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
74 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
74 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; inline; |
75 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
75 function RealRateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
|
76 function RateHammer(Me: PGear): LongInt; |
76 function RateHammer(Me: PGear): LongInt; |
77 |
77 |
78 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; |
78 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; |
79 function AIrndSign(num: LongInt): LongInt; |
79 function AIrndSign(num: LongInt): LongInt; |
80 |
80 |
112 Targets.reset:= false; |
112 Targets.reset:= false; |
113 end; |
113 end; |
114 procedure FillTargets; |
114 procedure FillTargets; |
115 var i, t: Longword; |
115 var i, t: Longword; |
116 f, e: LongInt; |
116 f, e: LongInt; |
|
117 iter: PGear; |
117 begin |
118 begin |
118 Targets.Count:= 0; |
119 Targets.Count:= 0; |
119 Targets.reset:= false; |
120 Targets.reset:= false; |
120 f:= 0; |
121 f:= 0; |
121 e:= 0; |
122 e:= 0; |
122 for t:= 0 to Pred(TeamsCount) do |
123 iter:= GearsList; |
123 with TeamsArray[t]^ do |
124 while iter <> nil do |
124 if not hasGone then |
125 begin |
125 begin |
126 if ((iter^.Kind = gtHedgehog) and |
126 for i:= 0 to cMaxHHIndex do |
127 (iter <> ThinkingHH) and |
127 if (Hedgehogs[i].Gear <> nil) |
128 (iter^.Health > iter^.Damage) and |
128 and (Hedgehogs[i].Gear <> ThinkingHH) |
129 not(iter^.Hedgehog^.Team^.hasgone)) or |
129 and (Hedgehogs[i].Gear^.Health > Hedgehogs[i].Gear^.Damage) |
130 ((iter^.Kind = gtExplosives) and |
130 then |
131 (iter^.Health > iter^.Damage)) or |
131 begin |
132 ((iter^.Kind = gtMine) and |
132 with Targets.ar[Targets.Count], Hedgehogs[i] do |
133 (iter^.Health = 0) and |
133 begin |
134 (iter^.Damage < 35)) and |
134 skip:= false; |
135 (Targets.Count < 256) then |
135 dead:= false; |
136 begin |
136 matters:= (Hedgehogs[i].Gear^.AIHints and aihDoesntMatter) = 0; |
137 with Targets.ar[Targets.Count] do |
137 |
138 begin |
138 Point.X:= hwRound(Gear^.X); |
139 skip:= false; |
139 Point.Y:= hwRound(Gear^.Y); |
140 dead:= false; |
140 if Clan <> CurrentTeam^.Clan then |
141 Kind:= iter^.Kind; |
141 begin |
142 matters:= (iter^.AIHints and aihDoesntMatter) = 0; |
142 Score:= Gear^.Health - Gear^.Damage; |
143 |
143 inc(e) |
144 Point.X:= hwRound(iter^.X); |
144 end else |
145 Point.Y:= hwRound(iter^.Y); |
145 begin |
146 if (iter^.Kind = gtHedgehog) then |
146 Score:= Gear^.Damage - Gear^.Health; |
147 if (iter^.Hedgehog^.Team^.Clan = CurrentTeam^.Clan) then |
147 inc(f) |
148 begin |
148 end |
149 Score:= iter^.Damage - iter^.Health; |
149 end; |
150 inc(f) |
150 inc(Targets.Count) |
151 end |
151 end; |
152 else |
152 end; |
153 begin |
|
154 Score:= iter^.Health - iter^.Damage; |
|
155 inc(e) |
|
156 end |
|
157 else if iter^.Kind = gtExplosives then Score:= iter^.Health - iter^.Damage |
|
158 else if iter^.Kind = gtMine then Score:= max(0,35-iter^.Damage) |
|
159 end; |
|
160 inc(Targets.Count) |
|
161 end; |
|
162 iter:= iter^.NextGear |
|
163 end; |
153 |
164 |
154 if e > f then friendlyfactor:= 300 + (e - f) * 30 |
165 if e > f then friendlyfactor:= 300 + (e - f) * 30 |
155 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e)) |
166 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e)) |
156 end; |
167 end; |
157 |
168 |
461 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
472 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
462 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
473 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
463 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0) * dmgMod) |
474 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0) * dmgMod) |
464 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure) * dmgMod) |
475 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure) * dmgMod) |
465 end; |
476 end; |
466 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
477 if Kind = gtHedgehog then |
467 if Score > 0 then |
478 begin |
468 inc(rate, (KillScore + Score div 10) * 1024) // Add a bit of a bonus for bigger hog drownings |
479 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
|
480 begin |
|
481 if Score > 0 then |
|
482 inc(rate, (KillScore + Score div 10) * 1024) // Add a bit of a bonus for bigger hog drownings |
|
483 else |
|
484 dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs |
|
485 end |
|
486 else if (dmg+fallDmg) >= abs(Score) then |
|
487 begin |
|
488 dead:= true; |
|
489 Targets.reset:= true; |
|
490 if dX < 0.035 then |
|
491 inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or (Flags and afTrackFall))); |
|
492 if Score > 0 then |
|
493 inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill |
|
494 else dec(rate, KillScore * friendlyfactor div 100 * 1024) |
|
495 end |
469 else |
496 else |
470 dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs |
497 begin |
471 else if (dmg+fallDmg) >= abs(Score) then |
498 if Score > 0 then |
|
499 inc(rate, (dmg + fallDmg) * 1024) |
|
500 else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024) |
|
501 end |
|
502 end |
|
503 // FIXME - need to make TraceFall calculate damage for barrels/mines correctly |
|
504 else if (Kind <> gtHedgehog) and (FallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
472 begin |
505 begin |
473 dead:= true; |
506 dead:= true; |
474 Targets.reset:= true; |
507 Targets.reset:= true; |
475 if dX < 0.035 then |
508 if Kind = gtExplosives then |
476 inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or (Flags and afTrackFall))); |
509 inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall))) |
477 if Score > 0 then |
510 else inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall))) |
478 inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill |
|
479 else |
|
480 dec(rate, KillScore * friendlyfactor div 100 * 1024) |
|
481 end |
511 end |
482 else |
512 end |
483 if Score > 0 then |
|
484 inc(rate, (dmg + fallDmg) * 1024) |
|
485 else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024) |
|
486 end; |
|
487 end; |
513 end; |
488 |
514 |
489 if hadSkips and (rate = 0) then |
515 if hadSkips and (rate = 0) then |
490 RealRateExplosion:= BadTurn |
516 RealRateExplosion:= BadTurn |
491 else |
517 else |
492 RealRateExplosion:= rate; |
518 RealRateExplosion:= rate; |
493 end; |
519 end; |
494 |
520 |
495 function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
521 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
496 var i, fallDmg, dmg, rate: LongInt; |
522 var i, fallDmg, dmg, rate: LongInt; |
497 dX, dY: real; |
523 dX, dY, pX, pY: real; |
498 begin |
524 begin |
499 fallDmg:= 0; |
525 fallDmg:= 0; |
500 dX:= gdX * 0.01 * kick; |
526 dX:= gdX * 0.01 * kick; |
501 dY:= gdY * 0.01 * kick; |
527 dY:= gdY * 0.01 * kick; |
502 rate:= 0; |
528 rate:= 0; |
510 if abs(Point.x - x) + abs(Point.y - y) < r then |
536 if abs(Point.x - x) + abs(Point.y - y) < r then |
511 dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); |
537 dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); |
512 |
538 |
513 if dmg > 0 then |
539 if dmg > 0 then |
514 begin |
540 begin |
|
541 pX:= Point.x; |
|
542 pY:= Point.y; |
515 if (Flags and afSetSkip <> 0) then skip:= true; |
543 if (Flags and afSetSkip <> 0) then skip:= true; |
516 if (Flags and afTrackFall <> 0) and (Score > 0) then |
544 if (Flags and afTrackFall <> 0) and (Score > 0) then |
517 fallDmg:= trunc(TraceShoveFall(Point.x, Point.y - 2, dX, dY) * dmgMod); |
545 fallDmg:= trunc(TraceShoveFall(pX, pY - 2, dX, dY) * dmgMod); |
518 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
546 if Kind = gtHedgehog then |
519 if Score > 0 then |
547 begin |
520 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
548 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
|
549 begin |
|
550 if Score > 0 then |
|
551 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
|
552 else |
|
553 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
|
554 end |
|
555 else if power+fallDmg >= abs(Score) then |
|
556 begin |
|
557 dead:= true; |
|
558 Targets.reset:= true; |
|
559 if dX < 0.035 then |
|
560 inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or (Flags and afTrackFall)) div 1024); |
|
561 if Score > 0 then |
|
562 inc(rate, KillScore) |
|
563 else |
|
564 dec(rate, KillScore * friendlyfactor div 100) |
|
565 end |
521 else |
566 else |
522 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
567 begin |
523 else if power+fallDmg >= abs(Score) then |
568 if Score > 0 then |
524 if Score > 0 then |
569 inc(rate, power+fallDmg) |
525 inc(rate, KillScore) |
570 else |
526 else |
571 dec(rate, (power+fallDmg) * friendlyfactor div 100) |
527 dec(rate, KillScore * friendlyfactor div 100) |
572 end |
528 else |
573 end |
529 if Score > 0 then |
574 // FIXME - need to make TraceFall calculate damage for barrels/mines correctly |
530 inc(rate, power+fallDmg) |
575 else if (Kind <> gtHedgehog) and (fallDmg >= 0) and ((power+fallDmg) >= Score) then |
531 else |
576 begin |
532 dec(rate, (power+fallDmg) * friendlyfactor div 100) |
577 dead:= true; |
533 end; |
578 Targets.reset:= true; |
|
579 if Kind = gtExplosives then |
|
580 inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) div 1024) |
|
581 else inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall)) div 1024) |
|
582 end |
|
583 end |
534 end; |
584 end; |
535 RateShove:= rate * 1024 |
585 RateShove:= rate * 1024 |
536 end; |
586 end; |
537 |
587 |
538 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; inline; |
588 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
539 begin |
|
540 RateShotgun:= RealRateShotgun(Me, gdX, gdY, x, y); |
|
541 ResetTargets; |
|
542 end; |
|
543 function RealRateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
|
544 var i, dmg, fallDmg, baseDmg, rate, erasure: LongInt; |
589 var i, dmg, fallDmg, baseDmg, rate, erasure: LongInt; |
545 pX, pY, dX, dY: real; |
590 pX, pY, dX, dY: real; |
546 hadSkips: boolean; |
591 hadSkips: boolean; |
547 begin |
592 begin |
548 rate:= 0; |
593 rate:= 0; |
587 else dX:= dX + 0.01; |
632 else dX:= dX + 0.01; |
588 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
633 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
589 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
634 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
590 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0) * dmgMod) |
635 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0) * dmgMod) |
591 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure) * dmgMod); |
636 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure) * dmgMod); |
592 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
637 if Kind = gtHedgehog then |
593 if Score > 0 then |
638 begin |
594 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
639 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
595 else |
640 begin |
596 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
641 if Score > 0 then |
597 else if (dmg+fallDmg) >= abs(Score) then |
642 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
|
643 else |
|
644 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
|
645 end |
|
646 else if (dmg+fallDmg) >= abs(Score) then |
|
647 begin |
|
648 dead:= true; |
|
649 Targets.reset:= true; |
|
650 if dX < 0.035 then |
|
651 inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall) div 1024); |
|
652 if Score > 0 then |
|
653 inc(rate, KillScore) |
|
654 else |
|
655 dec(rate, KillScore * friendlyfactor div 100) |
|
656 end |
|
657 else if Score > 0 then |
|
658 inc(rate, dmg+fallDmg) |
|
659 else dec(rate, (dmg+fallDmg) * friendlyfactor div 100) |
|
660 end |
|
661 // FIXME - need to make TraceFall calculate damage for barrels/mines correctly |
|
662 else if (Kind <> gtHedgehog) and (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
598 begin |
663 begin |
599 dead:= true; |
664 dead:= true; |
600 Targets.reset:= true; |
665 Targets.reset:= true; |
601 if dX < 0.035 then |
666 if Kind = gtExplosives then |
602 inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall) div 1024); |
667 inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or afTrackFall) div 1024) |
603 if Score > 0 then |
668 else inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or afTrackFall) div 1024) |
604 inc(rate, KillScore) |
|
605 else |
|
606 dec(rate, KillScore * friendlyfactor div 100) |
|
607 end |
669 end |
608 else |
670 end |
609 if Score > 0 then |
|
610 inc(rate, dmg+fallDmg) |
|
611 else |
|
612 dec(rate, (dmg+fallDmg) * friendlyfactor div 100) |
|
613 end; |
|
614 end; |
671 end; |
615 |
672 |
616 if hadSkips and (rate = 0) then |
673 if hadSkips and (rate = 0) then |
617 RealRateShotgun:= BadTurn |
674 RateShotgun:= BadTurn |
618 else |
675 else |
619 RealRateShotgun:= rate * 1024; |
676 RateShotgun:= rate * 1024; |
|
677 ResetTargets; |
620 end; |
678 end; |
621 |
679 |
622 function RateHammer(Me: PGear): LongInt; |
680 function RateHammer(Me: PGear): LongInt; |
623 var x, y, i, r, rate: LongInt; |
681 var x, y, i, r, rate: LongInt; |
624 begin |
682 begin |