hedgewars/uAIMisc.pas
branchtransitional_engine
changeset 15900 128ace913837
parent 15753 72f735c03fec
child 15901 f39f0f614dbf
equal deleted inserted replaced
15899:73cdc306888f 15900:128ace913837
    69 
    69 
    70 procedure initModule;
    70 procedure initModule;
    71 procedure freeModule;
    71 procedure freeModule;
    72 
    72 
    73 procedure FillTargets;
    73 procedure FillTargets;
    74 procedure ResetTargets; inline;
    74 procedure ResetTargets;
    75 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline;
    75 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt);
    76 procedure FillBonuses(isAfterAttack: boolean);
    76 procedure FillBonuses(isAfterAttack: boolean);
    77 procedure AwareOfExplosion(x, y, r: LongInt); inline;
    77 procedure AwareOfExplosion(x, y, r: LongInt);
    78 
    78 
    79 function  RatePlace(Gear: PGear): LongInt;
    79 function  RatePlace(Gear: PGear): LongInt;
    80 function  CheckWrap(x: real): real; inline;
    80 function  CheckWrap(x: real): real;
    81 function  TestColl(x, y, r: LongInt): boolean; inline;
    81 function  TestColl(x, y, r: LongInt): boolean;
    82 function  TestCollHogsOrObjects(x, y, r: LongInt): boolean; inline;
    82 function  TestCollHogsOrObjects(x, y, r: LongInt): boolean;
    83 function  TestCollExcludingObjects(x, y, r: LongInt): boolean; inline;
    83 function  TestCollExcludingObjects(x, y, r: LongInt): boolean;
    84 function  TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
    84 function  TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean;
    85 
    85 
    86 function  RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline;
    86 function  RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
    87 function  RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline;
    87 function  RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
    88 function  RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
    88 function  RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
    89 function  RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
    89 function  RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
    90 function  RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
    90 function  RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
    91 function  RateSeduction(Me: PGear): LongInt;
    91 function  RateSeduction(Me: PGear): LongInt;
    92 function  RateResurrector(Me: PGear): LongInt;
    92 function  RateResurrector(Me: PGear): LongInt;
    93 function  RateHammer(Me: PGear): LongInt;
    93 function  RateHammer(Me: PGear): LongInt;
    94 
    94 
    95 function  HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
    95 function  HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
    96 function  AIrndSign(num: LongInt): LongInt; inline;
    96 function  AIrndSign(num: LongInt): LongInt;
    97 function  AIrndOffset(targ: TTarget; Level: LongWord): LongInt; inline;
    97 function  AIrndOffset(targ: TTarget; Level: LongWord): LongInt;
    98 
    98 
    99 var ThinkingHH: PGear;
    99 var ThinkingHH: PGear;
   100     Targets: TTargets;
   100     Targets: TTargets;
   101 
   101 
   102     bonuses: TBonuses;
   102     bonuses: TBonuses;
   107       ResurrectScore = 100;
   107       ResurrectScore = 100;
   108 var friendlyfactor: LongInt = 300;
   108 var friendlyfactor: LongInt = 300;
   109 var dmgMod: real = 1.0;
   109 var dmgMod: real = 1.0;
   110 
   110 
   111 implementation
   111 implementation
   112 uses uCollisions, uVariables, uUtils, uGearsUtils, uAIAmmoTests;
   112 uses uCollisions, uVariables, uUtils, uGearsUtils, uAIAmmoTests, uLandUtils;
   113 
   113 
   114 var
   114 var
   115     KnownExplosion: record
   115     KnownExplosion: record
   116         X, Y, Radius: LongInt
   116         X, Y, Radius: LongInt
   117         end = (X: 0; Y: 0; Radius: 0);
   117         end = (X: 0; Y: 0; Radius: 0);
   118 
   118 
   119 procedure ResetTargets; inline;
   119 procedure ResetTargets;
   120 var i: LongWord;
   120 var i: LongWord;
   121 begin
   121 begin
   122 if Targets.reset then
   122 if Targets.reset then
   123     for i:= 0 to Targets.Count do
   123     for i:= 0 to Targets.Count do
   124         Targets.ar[i].dead:= false;
   124         Targets.ar[i].dead:= false;
   198 
   198 
   199 if e > f then friendlyfactor:= 300 + (e - f) * 30
   199 if e > f then friendlyfactor:= 300 + (e - f) * 30
   200 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e))
   200 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e))
   201 end;
   201 end;
   202 
   202 
   203 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline;
   203 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt);
   204 begin
   204 begin
   205 if(bonuses.Count < MAXBONUS) then
   205 if(bonuses.Count < MAXBONUS) then
   206     begin
   206     begin
   207     bonuses.ar[bonuses.Count].x:= x;
   207     bonuses.ar[bonuses.Count].x:= x;
   208     bonuses.ar[bonuses.Count].y:= y;
   208     bonuses.ar[bonuses.Count].y:= y;
   210     bonuses.ar[bonuses.Count].Score:= s;
   210     bonuses.ar[bonuses.Count].Score:= s;
   211     inc(bonuses.Count);
   211     inc(bonuses.Count);
   212     end;
   212     end;
   213 end;
   213 end;
   214 
   214 
   215 procedure AddWalkBonus(x, y: LongInt; r: Longword; s: LongInt); inline;
   215 procedure AddWalkBonus(x, y: LongInt; r: Longword; s: LongInt);
   216 begin
   216 begin
   217 if(walkbonuses.Count < MAXBONUS div 8) then
   217 if(walkbonuses.Count < MAXBONUS div 8) then
   218     begin
   218     begin
   219     walkbonuses.ar[walkbonuses.Count].x:= x;
   219     walkbonuses.ar[walkbonuses.Count].x:= x;
   220     walkbonuses.ar[walkbonuses.Count].y:= y;
   220     walkbonuses.ar[walkbonuses.Count].y:= y;
   332             AddBonus(X, Y, Radius, Score);
   332             AddBonus(X, Y, Radius, Score);
   333     walkbonuses.Count:= 0
   333     walkbonuses.Count:= 0
   334     end;
   334     end;
   335 end;
   335 end;
   336 
   336 
   337 procedure AwareOfExplosion(x, y, r: LongInt); inline;
   337 procedure AwareOfExplosion(x, y, r: LongInt);
   338 begin
   338 begin
   339     KnownExplosion.X:= x;
   339     KnownExplosion.X:= x;
   340     KnownExplosion.Y:= y;
   340     KnownExplosion.Y:= y;
   341     KnownExplosion.Radius:= r
   341     KnownExplosion.Radius:= r
   342 end;
   342 end;
   361                 inc(rate, Score * (Radius - r))
   361                 inc(rate, Score * (Radius - r))
   362         end;
   362         end;
   363     RatePlace:= rate;
   363     RatePlace:= rate;
   364 end;
   364 end;
   365 
   365 
   366 function CheckWrap(x: real): real; inline;
   366 function CheckWrap(x: real): real;
   367 begin
   367 begin
   368     if WorldEdge = weWrap then
   368     if WorldEdge = weWrap then
   369         if (x < leftX) then
   369         if (x < leftX) then
   370              x:= x + (rightX - leftX)
   370              x:= x + (rightX - leftX)
   371         else if x > rightX then    
   371         else if x > rightX then
   372              x:= x - (rightX - leftX);
   372              x:= x - (rightX - leftX);
   373     CheckWrap:= x;
   373     CheckWrap:= x;
   374 end;
   374 end;
   375 
   375 
   376 function CheckBounds(x, y, r: Longint): boolean; inline;
   376 function CheckBounds(x, y, r: Longint): boolean;
   377 begin
   377 begin
   378     CheckBounds := (((x-r) and LAND_WIDTH_MASK) = 0) and
   378     CheckBounds := (((x-r) and LAND_WIDTH_MASK) = 0) and
   379         (((x+r) and LAND_WIDTH_MASK) = 0) and
   379         (((x+r) and LAND_WIDTH_MASK) = 0) and
   380         (((y-r) and LAND_HEIGHT_MASK) = 0) and
   380         (((y-r) and LAND_HEIGHT_MASK) = 0) and
   381         (((y+r) and LAND_HEIGHT_MASK) = 0);
   381         (((y+r) and LAND_HEIGHT_MASK) = 0);
   382 end;
   382 end;
   383 
   383 
   384 
   384 
   385 // Check for collision with anything
   385 // Check for collision with anything
   386 function TestCollWithEverything(x, y, r: LongInt): boolean; inline;
   386 function TestCollWithEverything(x, y, r: LongInt): boolean;
   387 begin
   387 begin
   388     if not CheckBounds(x, y, r) then
   388     if not CheckBounds(x, y, r) then
   389         exit(false);
   389         exit(false);
   390 
   390 
   391     if (Land[y-r, x-r] <> 0) or
   391     if (LandGet(y-r, x-r) <> 0) or
   392        (Land[y+r, x-r] <> 0) or
   392        (LandGet(y+r, x-r) <> 0) or
   393        (Land[y-r, x+r] <> 0) or
   393        (LandGet(y-r, x+r) <> 0) or
   394        (Land[y+r, x+r] <> 0) then
   394        (LandGet(y+r, x+r) <> 0) then
   395        exit(true);
   395        exit(true);
   396 
   396 
   397     TestCollWithEverything := false;
   397     TestCollWithEverything := false;
   398 end;
   398 end;
   399 
   399 
   400 // Check for collision with non-objects
   400 // Check for collision with non-objects
   401 function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline;
   401 function TestCollExcludingObjects(x, y, r: LongInt): boolean;
   402 begin
   402 begin
   403     if not CheckBounds(x, y, r) then
   403     if not CheckBounds(x, y, r) then
   404         exit(false);
   404         exit(false);
   405 
   405 
   406     if (Land[y-r, x-r] > lfAllObjMask) or
   406     if (LandGet(y-r, x-r) > lfAllObjMask) or
   407        (Land[y+r, x-r] > lfAllObjMask) or
   407        (LandGet(y+r, x-r) > lfAllObjMask) or
   408        (Land[y-r, x+r] > lfAllObjMask) or
   408        (LandGet(y-r, x+r) > lfAllObjMask) or
   409        (Land[y+r, x+r] > lfAllObjMask) then
   409        (LandGet(y+r, x+r) > lfAllObjMask) then
   410        exit(true);
   410        exit(true);
   411 
   411 
   412     TestCollExcludingObjects:= false;
   412     TestCollExcludingObjects:= false;
   413 end;
   413 end;
   414 
   414 
   415 // Check for collision with something other than current hedgehog or crate
   415 // Check for collision with something other than current hedgehog or crate
   416 function TestColl(x, y, r: LongInt): boolean; inline;
   416 function TestColl(x, y, r: LongInt): boolean;
   417 begin
   417 begin
   418     if not CheckBounds(x, y, r) then
   418     if not CheckBounds(x, y, r) then
   419         exit(false);
   419         exit(false);
   420 
   420 
   421     if (Land[y-r, x-r] and lfNotCurHogCrate <> 0) or
   421     if (LandGet(y-r, x-r) and lfNotCurHogCrate <> 0) or
   422        (Land[y+r, x-r] and lfNotCurHogCrate <> 0) or
   422        (LandGet(y+r, x-r) and lfNotCurHogCrate <> 0) or
   423        (Land[y-r, x+r] and lfNotCurHogCrate <> 0) or
   423        (LandGet(y-r, x+r) and lfNotCurHogCrate <> 0) or
   424        (Land[y+r, x+r] and lfNotCurHogCrate <> 0) then
   424        (LandGet(y+r, x+r) and lfNotCurHogCrate <> 0) then
   425        exit(true);
   425        exit(true);
   426 
   426 
   427     TestColl:= false;
   427     TestColl:= false;
   428 end;
   428 end;
   429 
   429 
   430 // Check for collision with hedgehog or object
   430 // Check for collision with hedgehog or object
   431 function TestCollHogsOrObjects(x, y, r: LongInt): boolean; inline;
   431 function TestCollHogsOrObjects(x, y, r: LongInt): boolean;
   432 begin
   432 begin
   433     if not CheckBounds(x, y, r) then
   433     if not CheckBounds(x, y, r) then
   434         exit(false);
   434         exit(false);
   435 
   435 
   436     if (Land[y-r, x-r] and lfAllObjMask <> 0) or
   436     if (LandGet(y-r, x-r) and lfAllObjMask <> 0) or
   437        (Land[y+r, x-r] and lfAllObjMask <> 0) or
   437        (LandGet(y+r, x-r) and lfAllObjMask <> 0) or
   438        (Land[y-r, x+r] and lfAllObjMask <> 0) or
   438        (LandGet(y-r, x+r) and lfAllObjMask <> 0) or
   439        (Land[y+r, x+r] and lfAllObjMask <> 0) then
   439        (LandGet(y+r, x+r) and lfAllObjMask <> 0) then
   440        exit(true);
   440        exit(true);
   441 
   441 
   442     TestCollHogsOrObjects:= false;
   442     TestCollHogsOrObjects:= false;
   443 end;
   443 end;
   444 
   444 
   445 // Check for collision with something other than the given "Me" gear.
   445 // Check for collision with something other than the given "Me" gear.
   446 // Wrapper to test various approaches.  If it works reasonably, will just replace.
   446 // Wrapper to test various approaches.  If it works reasonably, will just replace.
   447 // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with...
   447 // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with...
   448 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
   448 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean;
   449 var MeX, MeY: LongInt;
   449 var MeX, MeY: LongInt;
   450 begin
   450 begin
   451     if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then
   451     if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then
   452     begin
   452     begin
   453         MeX:= hwRound(Me^.X);
   453         MeX:= hwRound(Me^.X);
   454         MeY:= hwRound(Me^.Y);
   454         MeY:= hwRound(Me^.Y);
   455         // We are still inside the hog. Skip radius test
   455         // We are still inside the hog. Skip radius test
   456         if ((sqr(x-MeX) + sqr(y-MeY)) < 256) and (Land[y, x] and lfObjMask = 0) then
   456         if ((sqr(x-MeX) + sqr(y-MeY)) < 256) and (LandGet(y, x) and lfObjMask = 0) then
   457             exit(false);
   457             exit(false);
   458     end;
   458     end;
   459     TestCollExcludingMe:= TestCollWithEverything(x, y, r)
   459     TestCollExcludingMe:= TestCollWithEverything(x, y, r)
   460 end;
   460 end;
   461 
   461 
   564             // returning -1 for drowning so it can be considered in the Rate routine
   564             // returning -1 for drowning so it can be considered in the Rate routine
   565             exit(-1)
   565             exit(-1)
   566     end;
   566     end;
   567 end;
   567 end;
   568 
   568 
   569 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline;
   569 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
   570 begin
   570 begin
   571     RateExplosion:= RealRateExplosion(Me, x, y, r, 0);
   571     RateExplosion:= RealRateExplosion(Me, x, y, r, 0);
   572     ResetTargets;
   572     ResetTargets;
   573 end;
   573 end;
   574 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline;
   574 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
   575 begin
   575 begin
   576     RateExplosion:= RealRateExplosion(Me, x, y, r, Flags);
   576     RateExplosion:= RealRateExplosion(Me, x, y, r, Flags);
   577     ResetTargets;
   577     ResetTargets;
   578 end;
   578 end;
   579 
   579 
   635 
   635 
   636                     if pX - x < 0 then dX:= -dX;
   636                     if pX - x < 0 then dX:= -dX;
   637                     if pY - y < 0 then dY:= -dY;
   637                     if pY - y < 0 then dY:= -dY;
   638 
   638 
   639                     if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
   639                     if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
   640                        (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
   640                        (LandGet(y+cHHRadius+2, x) and lfIndestructible <> 0) then
   641                          fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod)
   641                          fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod)
   642                     else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod)
   642                     else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod)
   643                     end;
   643                     end;
   644                 if Kind = gtHedgehog then
   644                 if Kind = gtHedgehog then
   645                     begin
   645                     begin
   829                     if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and
   829                     if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and
   830                        (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or
   830                        (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or
   831                         ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then
   831                         ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then
   832                        dX:= 0;
   832                        dX:= 0;
   833                     if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
   833                     if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
   834                        (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
   834                        (LandGet(y+cHHRadius+2, x) and lfIndestructible <> 0) then
   835                          fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod)
   835                          fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod)
   836                     else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod)
   836                     else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod)
   837                     end;
   837                     end;
   838                 if Kind = gtHedgehog then
   838                 if Kind = gtHedgehog then
   839                     begin
   839                     begin
  1204 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0);
  1204 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0);
  1205 
  1205 
  1206 HHJump(AltGear, jmpHJump, GoInfo);
  1206 HHJump(AltGear, jmpHJump, GoInfo);
  1207 end;
  1207 end;
  1208 
  1208 
  1209 function AIrndSign(num: LongInt): LongInt; inline;
  1209 function AIrndSign(num: LongInt): LongInt;
  1210 begin
  1210 begin
  1211 if random(2) = 0 then
  1211 if random(2) = 0 then
  1212     AIrndSign:=   num
  1212     AIrndSign:=   num
  1213 else
  1213 else
  1214     AIrndSign:= - num
  1214     AIrndSign:= - num
  1215 end;
  1215 end;
  1216 
  1216 
  1217 function AIrndOffset(targ: TTarget; Level: LongWord): LongInt; inline;
  1217 function AIrndOffset(targ: TTarget; Level: LongWord): LongInt;
  1218 begin
  1218 begin
  1219 if Level <> 1 then exit(0);
  1219 if Level <> 1 then exit(0);
  1220 // at present level 2 doesn't track falls on most things
  1220 // at present level 2 doesn't track falls on most things
  1221 //if Level = 2 then exit(round(targ.Radius*(random(5)-2)/2));
  1221 //if Level = 2 then exit(round(targ.Radius*(random(5)-2)/2));
  1222 AIrndOffset := targ.Radius*(random(7)-3)*2
  1222 AIrndOffset := targ.Radius*(random(7)-3)*2