--- a/ChangeLog.txt Mon Jul 06 00:25:13 2020 +0200
+++ b/ChangeLog.txt Mon Jul 06 01:46:22 2020 +0200
@@ -6,7 +6,7 @@
+ Easier to push hogs around with blowtorch
+ Backjumps are now a bit easier
+ Teach computer players how to ...
- + - use drill strike, piano strike, air mine, cleaver, seduction, laser sight
+ + - use drill strike, piano strike, air mine, cleaver, seduction, resurrector, laser sight
+ - use mine strike (0 seconds only)
+ - use RC plane (very basic)
+ - drop mines from a cliff
--- a/hedgewars/uAIAmmoTests.pas Mon Jul 06 00:25:13 2020 +0200
+++ b/hedgewars/uAIAmmoTests.pas Mon Jul 06 01:46:22 2020 +0200
@@ -64,6 +64,7 @@
function TestPiano(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
function TestTeleport(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
function TestHammer(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
+function TestResurrector(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
function TestCake(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
function TestSeduction(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
function TestDynamite(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
@@ -130,7 +131,7 @@
(proc: nil; flags: 0), // amFlamethrower
(proc: @TestSMine; flags: 0), // amSMine
(proc: @TestHammer; flags: amtest_NoTarget or amtest_NoInvulnerable), // amHammer
- (proc: nil; flags: 0), // amResurrector
+ (proc: @TestResurrector; flags: amtest_NoTarget or amtest_NoInvulnerable or amtest_NoVampiric), // amResurrector
(proc: @TestDrillStrike; flags: amtest_Rare), // amDrillStrike
(proc: nil; flags: 0), // amSnowball
(proc: nil; flags: 0), // amTardis
@@ -1487,6 +1488,40 @@
TestAirAttack:= valueResult;
end;
+function TestResurrector(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
+var rate, heal: LongInt;
+begin
+Flags:= Flags; // avoid compiler hint
+Targ:= Targ;
+
+if (Level = 5) then
+ exit(BadTurn);
+
+if (Me^.Health <= 1) then
+ exit(BadTurn);
+
+if (Level <= 2) and (Me^.Hedgehog^.Effects[hePoisoned] > 0) then
+ // Sacrifice almost all health if poisoned
+ heal:= Me^.Health - 1
+else
+ // Sacrifice up to 10% of own health
+ heal:= (Me^.Health div 10);
+
+ap.ExplR:= 0;
+ap.Time:= 0;
+if (GameFlags and gfInfAttack) = 0 then
+ ap.Power:= max(min(500 * heal - 500, 10000), 10)
+else
+ // Shorter attack duration in inf attack because the clock is ticking!
+ ap.Power:= max(min(500 * heal - 500, 3000), 10);
+ap.Angle:= 0;
+
+rate:= RateResurrector(Me);
+if rate <= 0 then
+ rate:= BadTurn;
+TestResurrector:= rate;
+end;
+
function TestDrillStrike(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
const cShift = 4;
Density : real = 1.0;
--- a/hedgewars/uAIMisc.pas Mon Jul 06 00:25:13 2020 +0200
+++ b/hedgewars/uAIMisc.pas Mon Jul 06 01:46:22 2020 +0200
@@ -88,6 +88,7 @@
function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
function RateSeduction(Me: PGear): LongInt;
+function RateResurrector(Me: PGear): LongInt;
function RateHammer(Me: PGear): LongInt;
function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
@@ -102,6 +103,7 @@
walkbonuses: Twalkbonuses;
const KillScore = 200;
+ ResurrectScore = 100;
var friendlyfactor: LongInt = 300;
var dmgMod: real = 1.0;
@@ -137,6 +139,8 @@
(Gear <> ThinkingHH) and
(Gear^.Health > Gear^.Damage) and
(not Gear^.Hedgehog^.Team^.hasgone)) or
+ ((Gear^.Kind = gtGrave) and
+ (Gear^.Health = 0)) or
((Gear^.Kind = gtExplosives) and
(Gear^.Health > Gear^.Damage)) or
((Gear^.Kind = gtMine) and
@@ -170,6 +174,17 @@
inc(e)
end;
end
+ else if Gear^.Kind = gtGrave then
+ if (Gear^.Hedgehog^.Team^.Clan = CurrentTeam^.Clan) then
+ begin
+ Score:= ResurrectScore;
+ inc(f);
+ end
+ else
+ begin
+ Score:= -ResurrectScore;
+ inc(e);
+ end
else if Gear^.Kind = gtExplosives then
Score:= Gear^.Health - Gear^.Damage
else if Gear^.Kind = gtMine then
@@ -923,6 +938,45 @@
RateSeduction:= rate * 1024;
end;
+function RateResurrector(Me: PGear): LongInt;
+var i, r, rate, pX, pY: LongInt;
+ meX, meY: hwFloat;
+ hadSkips: boolean;
+begin
+meX:= Me^.X;
+meY:= Me^.Y;
+rate:= 0;
+for i:= 0 to Targets.Count do
+ if (Targets.ar[i].Kind = gtGrave) and (not Targets.ar[i].dead) then
+ with Targets.ar[i] do
+ begin
+ pX:= Point.X;
+ pY:= Point.Y;
+
+ if (not matters) then
+ hadSkips:= true
+ else if matters and (abs(pX - hwRound(meX)) + abs(pY - hwRound(meY)) < cResurrectorDist) then
+ begin
+ r:= trunc(sqrt(sqr(abs(pX - hwRound(meX)))+sqr(abs(pY - hwRound(meY)))));
+ if r < cResurrectorDist then
+ begin
+ if Score > 0 then
+ inc(rate, Score * 1024)
+ else
+ inc(rate, Score * friendlyFactor div 100 * 1024);
+ // a "dead" grave is a grave that we have resurrected
+ dead:= true;
+ Targets.reset:= true;
+ end;
+ end;
+ end;
+
+if hadSkips and (rate <= 0) then
+ RateResurrector:= BadTurn
+else
+ RateResurrector:= rate * 1024;
+end;
+
function RateHammer(Me: PGear): LongInt;
var x, y, i, r, rate: LongInt;
hadSkips: boolean;