# HG changeset patch # User nemo # Date 1331511151 14400 # Node ID 7d2c6cdb816a0a77ae8cf74d4771a5341fb20022 # Parent 44ad49a3a126b6e8f7fb44c70cf43fc93d0277db Start on adding drowning bonus to bat/firepunch/whip. AI still is not smart enough to change direction when firepunching to face the water, or change the angle of the bat. Also try to weight cost of switches based on how many switches were available. diff -r 44ad49a3a126 -r 7d2c6cdb816a hedgewars/uAI.pas --- a/hedgewars/uAI.pas Sun Mar 11 18:28:32 2012 -0400 +++ b/hedgewars/uAI.pas Sun Mar 11 20:12:31 2012 -0400 @@ -199,7 +199,7 @@ Stack.Count:= 0; for a:= Low(TAmmoType) to High(TAmmoType) do - CanUseAmmo[a]:= Assigned(AmmoTests[a].proc) and HHHasAmmo(Me^.Hedgehog^, a); + CanUseAmmo[a]:= Assigned(AmmoTests[a].proc) and (HHHasAmmo(Me^.Hedgehog^, a) > 0); BotLevel:= Me^.Hedgehog^.BotLevel; @@ -291,8 +291,8 @@ function Think(Me: Pointer): ptrint; var BackMe, WalkMe: TGear; - StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i: Longword; - switchImmediatelyAvailable, switchAvailable: boolean; + StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i, switchCount: Longword; + switchImmediatelyAvailable: boolean; Actions: TActions; begin InterlockedIncrement(hasThread); @@ -302,7 +302,7 @@ switchesNum:= 0; switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher); -switchAvailable:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch); +switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch); if (PGear(Me)^.State and gstAttacked) = 0 then if Targets.Count > 0 then @@ -316,10 +316,10 @@ Actions.Score:= 0; if switchesNum > 0 then begin - if not switchImmediatelyAvailable then + if not switchImmediatelyAvailable then begin - // when AI has to use switcher, make it cost smth - Actions.Score:= -20000; + // when AI has to use switcher, make it cost smth unless they have a lot of switches + if (SwitchCount < 10) then Actions.Score:= (-27+SwitchCount*3)*4000; AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0); AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0); AddAction(Actions, aia_attack, aim_release, 1, 0, 0); @@ -336,7 +336,7 @@ inc(switchesNum); - until (not (switchImmediatelyAvailable or switchAvailable)) + until (not (switchImmediatelyAvailable or (switchCount > 0))) or StopThinking or (itHedgehog = currHedgehogIndex) or BestActions.isWalkingToABetterPlace; diff -r 44ad49a3a126 -r 7d2c6cdb816a hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Sun Mar 11 18:28:32 2012 -0400 +++ b/hedgewars/uAIAmmoTests.pas Sun Mar 11 20:12:31 2012 -0400 @@ -41,6 +41,7 @@ function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; @@ -66,7 +67,7 @@ (proc: @TestDesertEagle; flags: 0), // amDEagle (proc: nil; flags: 0), // amDynamite (proc: @TestFirePunch; flags: 0), // amFirePunch - (proc: @TestFirePunch; flags: 0), // amWhip + (proc: @TestWhip; flags: 0), // amWhip (proc: @TestBaseballBat; flags: 0), // amBaseballBat (proc: nil; flags: 0), // amParachute (proc: @TestAirAttack; flags: amtest_OnTurn), // amAirAttack @@ -618,7 +619,8 @@ ap.Angle:= cMaxAngle div 4 else ap.Angle:= - cMaxAngle div 4; -valueResult:= RateShove(Me, hwRound(x) + 10 * hwSign(int2hwFloat(Targ.X) - x), hwRound(y), 15, 30); + +valueResult:= RateShove(Me, hwRound(x) + 10 * hwSign(int2hwFloat(Targ.X) - x), hwRound(y), 15, 30, 115, hwSign(Me^.dX)*0.353, -0.353, 1); if valueResult <= 0 then valueResult:= BadTurn else @@ -641,7 +643,7 @@ or (Abs(hwRound(y) - 50 - Targ.Y) > 50) then begin if TestColl(hwRound(x), hwRound(y) - 16, 6) - and (RateShove(Me, hwRound(x) + 10 * hwSign(Me^.dX), hwRound(y) - 40, 30, 30) = 0) then + and (RateShove(Me, hwRound(x) + 10 * hwSign(Me^.dX), hwRound(y) - 40, 30, 30, 40, hwSign(Me^.dX)*0.45, -0.9, 1) = 0) then valueResult:= Succ(BadTurn) else valueResult:= BadTurn; @@ -651,7 +653,7 @@ valueResult:= 0; for i:= 0 to 4 do valueResult:= valueResult + RateShove(Me, hwRound(x) + 10 * hwSign(int2hwFloat(Targ.X) - x), - hwRound(y) - 20 * i - 5, 10, 30); + hwRound(y) - 20 * i - 5, 10, 30, 40, hwSign(Me^.dX)*0.45, -0.9, 1); if valueResult <= 0 then valueResult:= BadTurn else @@ -660,6 +662,40 @@ TestFirePunch:= valueResult; end; +function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +var i, valueResult: LongInt; + x, y: hwFloat; +begin +Level:= Level; // avoid compiler hint +ap.ExplR:= 0; +ap.Time:= 0; +ap.Power:= 1; +ap.Angle:= 0; +x:= Me^.X; +y:= Me^.Y; +if (Abs(hwRound(x) - Targ.X) > 25) +or (Abs(hwRound(y) - 50 - Targ.Y) > 50) then + begin + if TestColl(hwRound(x), hwRound(y) - 16, 6) + and (RateShove(Me, hwRound(x) + 10 * hwSign(Me^.dX), hwRound(y) - 40, 30, 30, 40, hwSign(Me^.dX), -0.8, 1) = 0) then + valueResult:= Succ(BadTurn) + else + valueResult:= BadTurn; + exit(valueResult) + end; + +valueResult:= 0; +for i:= 0 to 4 do + valueResult:= valueResult + RateShove(Me, hwRound(x) + 10 * hwSign(int2hwFloat(Targ.X) - x), + hwRound(y) - 20 * i - 5, 10, 30, 40, hwSign(Me^.dX), -0.8, 1); +if valueResult <= 0 then + valueResult:= BadTurn +else + inc(valueResult); + +TestWhip:= valueResult; +end; + function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; var rate: LongInt; begin diff -r 44ad49a3a126 -r 7d2c6cdb816a hedgewars/uAIMisc.pas --- a/hedgewars/uAIMisc.pas Sun Mar 11 18:28:32 2012 -0400 +++ b/hedgewars/uAIMisc.pas Sun Mar 11 20:12:31 2012 -0400 @@ -54,7 +54,7 @@ function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; function TestColl(x, y, r: LongInt): boolean; inline; function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord = 0): LongInt; -function RateShove(Me: PGear; x, y, r, power: LongInt): LongInt; +function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; function RateShotgun(Me: PGear; x, y: LongInt): LongInt; function RateHammer(Me: PGear): LongInt; function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; @@ -267,11 +267,25 @@ y:= y + dY; dY:= dY + cGravityf; skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner)); + // consider adding dX/dY calc here for fall damage if not skipLandCheck and TestCollWithLand(trunc(x), trunc(y), cHHRadius) then exit(false); if (y > cWaterLine) or (x > 4096) or (x < 0) then exit(true); end; end; +function TraceShoveDrown(Me: PGear; x, y, dX, dY: Real): boolean; +begin + while true do + begin + x:= x + dX; + y:= y + dY; + dY:= dY + cGravityf; + // consider adding dX/dY calc here for fall damage + if TestCollExcludingMe(Me, trunc(x), trunc(y), cHHRadius) then exit(false); + if (y > cWaterLine) or (x > 4096) or (x < 0) then exit(true); + end; +end; + // Flags are not defined yet but 1 for checking drowning and 2 for assuming land erasure. function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord = 0): LongInt; var i, dmg, dmgBase, rate, erasure: LongInt; @@ -305,9 +319,7 @@ end; if (Flags and 1 <> 0) and TraceDrown(x, y, Point.x, Point.y, dX, dY, erasure) then if Score > 0 then - begin inc(rate, KillScore) - end else dec(rate, KillScore * friendlyfactor div 100) else if dmg >= abs(Score) then @@ -325,19 +337,32 @@ RateExplosion:= rate * 1024; end; -function RateShove(Me: PGear; x, y, r, power: LongInt): LongInt; +function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; var i, dmg, rate: LongInt; + dX, dY: real; begin Me:= Me; // avoid compiler hint rate:= 0; for i:= 0 to Pred(Targets.Count) do with Targets.ar[i] do begin - dmg:= r - hwRound(DistanceI(Point.x - x, Point.y - y)); + dmg:= 0; + if abs(Point.x - x) + abs(Point.y - y) < r then + dmg:= r - hwRound(DistanceI(Point.x - x, Point.y - y)); dmg:= hwRound(_0_01 * cDamageModifier * dmg * cDamagePercent); if dmg > 0 then begin - if power >= abs(Score) then + if Flags and 1 <> 0 then + begin + dX:= gdX * 0.005 * kick; + dY:= gdY * 0.005 * kick; + end; + if (Flags and 1 <> 0) and TraceShoveDrown(Me, Point.x, Point.y, dX, dY) then + if Score > 0 then + inc(rate, KillScore) + else + dec(rate, KillScore * friendlyfactor div 100) + else if power >= abs(Score) then if Score > 0 then inc(rate, KillScore) else diff -r 44ad49a3a126 -r 7d2c6cdb816a hedgewars/uAmmos.pas --- a/hedgewars/uAmmos.pas Sun Mar 11 18:28:32 2012 -0400 +++ b/hedgewars/uAmmos.pas Sun Mar 11 20:12:31 2012 -0400 @@ -33,7 +33,7 @@ procedure AssignStores; procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType); procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType; cnt: LongWord); -function HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): boolean; +function HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): LongWord; procedure PackAmmo(Ammo: PHHAmmo; Slot: LongInt); procedure OnUsedAmmo(var Hedgehog: THedgehog); procedure ApplyAngleBounds(var Hedgehog: THedgehog; AmmoType: TAmmoType); @@ -277,7 +277,7 @@ end; end; -function HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): boolean; +function HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): LongWord; var slot, ami: LongInt; begin Slot:= Ammoz[Ammo].Slot; @@ -286,10 +286,12 @@ begin with Hedgehog.Ammo^[Slot, ami] do if (AmmoType = Ammo) then - exit((Count > 0) and (Hedgehog.Team^.Clan^.TurnNumber > Ammoz[AmmoType].SkipTurns)); + if Hedgehog.Team^.Clan^.TurnNumber > Ammoz[AmmoType].SkipTurns then + exit(Count) + else exit(0); inc(ami) end; -HHHasAmmo:= false +HHHasAmmo:= 0 end; procedure ApplyAngleBounds(var Hedgehog: THedgehog; AmmoType: TAmmoType);