hedgewars/uAIMisc.pas
branchui-scaling
changeset 15283 c4fd2813b127
parent 14764 b3fa6a19fc25
child 15355 09fc16926855
equal deleted inserted replaced
13390:0135e64c6c66 15283:c4fd2813b127
    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
   456     odX:= dX;
   472     odX:= dX;
   457     odY:= dY;
   473     odY:= dY;
   458 //v:= random($FFFFFFFF);
   474 //v:= random($FFFFFFFF);
   459     while true do
   475     while true do
   460         begin
   476         begin
       
   477         x:= CheckWrap(x);
   461         x:= x + dX;
   478         x:= x + dX;
   462         y:= y + dY;
   479         y:= y + dY;
   463         dY:= dY + cGravityf;
   480         dY:= dY + cGravityf;
   464 
   481 
   465 {        if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then
   482 {        if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) 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;