hedgewars/uAIMisc.pas
changeset 6580 6155187bf599
parent 6474 42e9773eedfd
child 6700 e04da46ee43c
equal deleted inserted replaced
6579:fc52f7c22c9b 6580:6155187bf599
    23 uses SDLh, uConsts, uFloat, uTypes;
    23 uses SDLh, uConsts, uFloat, uTypes;
    24 
    24 
    25 const MAXBONUS = 1024;
    25 const MAXBONUS = 1024;
    26 
    26 
    27 type TTarget = record
    27 type TTarget = record
    28                Point: TPoint;
    28     Point: TPoint;
    29                Score: LongInt;
    29     Score: LongInt;
    30                end;
    30     end;
    31      TTargets = record
    31 TTargets = record
    32                 Count: Longword;
    32     Count: Longword;
    33                 ar: array[0..Pred(cMaxHHs)] of TTarget;
    33     ar: array[0..Pred(cMaxHHs)] of TTarget;
    34                 end;
    34     end;
    35      TJumpType = (jmpNone, jmpHJump, jmpLJump);
    35 TJumpType = (jmpNone, jmpHJump, jmpLJump);
    36      TGoInfo = record
    36 TGoInfo = record
    37                Ticks: Longword;
    37     Ticks: Longword;
    38                FallPix: Longword;
    38     FallPix: Longword;
    39                JumpType: TJumpType;
    39     JumpType: TJumpType;
    40                end;
    40     end;
    41      TBonus = record
    41 TBonus = record
    42               X, Y: LongInt;
    42     X, Y: LongInt;
    43               Radius: LongInt;
    43     Radius: LongInt;
    44               Score: LongInt;
    44     Score: LongInt;
    45               end;
    45     end;
    46 
    46 
    47 procedure initModule;
    47 procedure initModule;
    48 procedure freeModule;
    48 procedure freeModule;
    49 
    49 
    50 procedure FillTargets;
    50 procedure FillTargets;
    62 
    62 
    63 var ThinkingHH: PGear;
    63 var ThinkingHH: PGear;
    64     Targets: TTargets;
    64     Targets: TTargets;
    65 
    65 
    66     bonuses: record
    66     bonuses: record
    67              Count: Longword;
    67         Count: Longword;
    68              ar: array[0..Pred(MAXBONUS)] of TBonus;
    68         ar: array[0..Pred(MAXBONUS)] of TBonus;
    69              end;
    69         end;
    70 
    70 
    71 implementation
    71 implementation
    72 uses uCollisions, uVariables, uUtils, uDebug;
    72 uses uCollisions, uVariables, uUtils, uDebug;
    73 
    73 
    74 const KillScore = 200;
    74 const KillScore = 200;
    75 
    75 
    76 var friendlyfactor: LongInt = 300;
    76 var friendlyfactor: LongInt = 300;
    77     KnownExplosion: record
    77     KnownExplosion: record
    78                     X, Y, Radius: LongInt
    78         X, Y, Radius: LongInt
    79                     end = (X: 0; Y: 0; Radius: 0);
    79         end = (X: 0; Y: 0; Radius: 0);
    80 
    80 
    81 procedure FillTargets;
    81 procedure FillTargets;
    82 var i, t: Longword;
    82 var i, t: Longword;
    83     f, e: LongInt;
    83     f, e: LongInt;
    84 begin
    84 begin
   133 MyClan:= ThinkingHH^.Hedgehog^.Team^.Clan;
   133 MyClan:= ThinkingHH^.Hedgehog^.Team^.Clan;
   134 Gear:= GearsList;
   134 Gear:= GearsList;
   135 while Gear <> nil do
   135 while Gear <> nil do
   136     begin
   136     begin
   137     if (filter = []) or (Gear^.Kind in filter) then
   137     if (filter = []) or (Gear^.Kind in filter) then
   138       case Gear^.Kind of
   138         case Gear^.Kind of
   139           gtCase: AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 33, 25);
   139             gtCase:
   140           gtFlame: if (Gear^.State and gsttmpFlag) <> 0 then
   140             AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 33, 25);
   141                   AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 20, -50);
   141             gtFlame:
       
   142                 if (Gear^.State and gsttmpFlag) <> 0 then
       
   143                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 20, -50);
   142 // avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow 
   144 // avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow 
   143           gtMine:  if ((Gear^.State and gstAttacking) = 0) and 
   145             gtMine:
   144                       (((cMineDudPercent < 90) and (Gear^.Health <> 0)) or
   146                 if ((Gear^.State and gstAttacking) = 0) and (((cMineDudPercent < 90) and (Gear^.Health <> 0))
   145                        (isAfterAttack and (Gear^.Health = 0) and (Gear^.Damage > 30))) then
   147                 or (isAfterAttack and (Gear^.Health = 0) and (Gear^.Damage > 30))) then
   146                           AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -50)
   148                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -50)
   147                       else if (Gear^.State and gstAttacking) <> 0 then
   149                 else if (Gear^.State and gstAttacking) <> 0 then
   148                           AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, -50); // mine is on
   150                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, -50); // mine is on
   149           gtExplosives: if isAfterAttack then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 75, -60+Gear^.Health);
   151                     
   150           gtSMine:    AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -30);
   152             gtExplosives:
   151           gtDynamite: AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -75);
   153             if isAfterAttack then
   152           gtHedgehog: begin
   154                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 75, -60+Gear^.Health);
   153                       if Gear^.Damage >= Gear^.Health then
   155                 
   154                           AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 60, -25)
   156             gtSMine:
   155                       else
   157                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -30);
   156                           if isAfterAttack and (ThinkingHH^.Hedgehog <> Gear^.Hedgehog) then
   158                 
   157                               if (ClansCount > 2) or (MyClan = Gear^.Hedgehog^.Team^.Clan) then
   159             gtDynamite:
   158                                   AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -3) // hedgehog-friend
   160                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -75);
   159                               else
   161                 
   160                                   AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, 3)
   162             gtHedgehog:
   161                       end;
   163                 begin
   162           end;
   164                 if Gear^.Damage >= Gear^.Health then
       
   165                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 60, -25)
       
   166                 else
       
   167                     if isAfterAttack and (ThinkingHH^.Hedgehog <> Gear^.Hedgehog) then
       
   168                         if (ClansCount > 2) or (MyClan = Gear^.Hedgehog^.Team^.Clan) then
       
   169                             AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -3) // hedgehog-friend
       
   170                         else
       
   171                             AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, 3)
       
   172                 end;
       
   173             end;
   163     Gear:= Gear^.NextGear
   174     Gear:= Gear^.NextGear
   164     end;
   175     end;
   165 if isAfterAttack and (KnownExplosion.Radius > 0) then
   176 if isAfterAttack and (KnownExplosion.Radius > 0) then
   166    with KnownExplosion do
   177     with KnownExplosion do
   167         AddBonus(X, Y, Radius + 10, -Radius);
   178         AddBonus(X, Y, Radius + 10, -Radius);
   168 end;
   179 end;
   169 
   180 
   170 procedure AwareOfExplosion(x, y, r: LongInt);
   181 procedure AwareOfExplosion(x, y, r: LongInt);
   171 begin
   182 begin
   197     if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then
   208     if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then
   198         begin
   209         begin
   199         MeX:= hwRound(Me^.X);
   210         MeX:= hwRound(Me^.X);
   200         MeY:= hwRound(Me^.Y);
   211         MeY:= hwRound(Me^.Y);
   201         // We are still inside the hog. Skip radius test
   212         // We are still inside the hog. Skip radius test
   202         if ((((x-MeX)*(x-MeX)) + ((y-MeY)*(y-MeY))) < 256) and
   213         if ((((x-MeX)*(x-MeX)) + ((y-MeY)*(y-MeY))) < 256) and ((Land[y, x] and $FF00) = 0) then
   203            ((Land[y, x] and $FF00) = 0) then exit(false);
   214             exit(false);
   204         end;
   215         end;
   205     exit(TestColl(x, y, r))
   216     exit(TestColl(x, y, r))
   206 end;
   217 end;
   207 
   218 
   208 function TestColl(x, y, r: LongInt): boolean;
   219 function TestColl(x, y, r: LongInt): boolean;
   209 var b: boolean;
   220 var b: boolean;
   210 begin
   221 begin
   211 b:= (((x-r) and LAND_WIDTH_MASK) = 0)and(((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] <> 0);
   222 b:= (((x-r) and LAND_WIDTH_MASK) = 0)and(((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] <> 0);
   212 if b then exit(true);
   223 if b then
       
   224     exit(true);
       
   225     
   213 b:=(((x-r) and LAND_WIDTH_MASK) = 0)and(((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] <> 0);
   226 b:=(((x-r) and LAND_WIDTH_MASK) = 0)and(((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] <> 0);
   214 if b then exit(true);
   227 if b then
       
   228     exit(true);
       
   229     
   215 b:=(((x+r) and LAND_WIDTH_MASK) = 0)and(((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] <> 0);
   230 b:=(((x+r) and LAND_WIDTH_MASK) = 0)and(((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] <> 0);
   216 if b then exit(true);
   231 if b then
       
   232     exit(true);
       
   233     
   217 TestColl:=(((x+r) and LAND_WIDTH_MASK) = 0)and(((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] <> 0)
   234 TestColl:=(((x+r) and LAND_WIDTH_MASK) = 0)and(((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] <> 0)
   218 end;
   235 end;
   219 
   236 
   220 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
   237 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
   221 var i, dmg, rate: LongInt;
   238 var i, dmg, rate: LongInt;
   222 begin
   239 begin
   223 rate:= 0;
   240 rate:= 0;
   224 // add our virtual position
   241 // add our virtual position
   225 with Targets.ar[Targets.Count] do
   242 with Targets.ar[Targets.Count] do
   226      begin
   243     begin
   227      Point.x:= hwRound(Me^.X);
   244     Point.x:= hwRound(Me^.X);
   228      Point.y:= hwRound(Me^.Y);
   245     Point.y:= hwRound(Me^.Y);
   229      Score:= - ThinkingHH^.Health
   246     Score:= - ThinkingHH^.Health
   230      end;
   247     end;
   231 // rate explosion
   248 // rate explosion
   232 for i:= 0 to Targets.Count do
   249 for i:= 0 to Targets.Count do
   233     with Targets.ar[i] do
   250     with Targets.ar[i] do
   234          begin
   251         begin
   235          dmg:= hwRound(_0_01 * cDamageModifier
   252         dmg:= hwRound(_0_01 * cDamageModifier * min((r + cHHRadius div 2 - LongInt(DistanceI(Point.x - x, Point.y - y).Round)) div 2, r) * cDamagePercent);
   236             * min((r + cHHRadius div 2 - LongInt(DistanceI(Point.x - x, Point.y - y).Round)) div 2, r) * cDamagePercent);
   253 
   237 
   254         if dmg > 0 then
   238          if dmg > 0 then
       
   239             begin
   255             begin
   240             if dmg >= abs(Score) then
   256             if dmg >= abs(Score) then
   241                if Score > 0 then inc(rate, KillScore)
   257                 if Score > 0 then
   242                             else dec(rate, KillScore * friendlyfactor div 100)
   258                     inc(rate, KillScore)
       
   259                 else
       
   260                     dec(rate, KillScore * friendlyfactor div 100)
   243             else
   261             else
   244                if Score > 0 then inc(rate, dmg)
   262                 if Score > 0 then
   245                             else dec(rate, dmg * friendlyfactor div 100)
   263                     inc(rate, dmg)
       
   264             else
       
   265                 dec(rate, dmg * friendlyfactor div 100)
   246             end;
   266             end;
   247          end;
   267         end;
   248 RateExplosion:= rate * 1024;
   268 RateExplosion:= rate * 1024;
   249 end;
   269 end;
   250 
   270 
   251 function RateShove(Me: PGear; x, y, r, power: LongInt): LongInt;
   271 function RateShove(Me: PGear; x, y, r, power: LongInt): LongInt;
   252 var i, dmg, rate: LongInt;
   272 var i, dmg, rate: LongInt;
   253 begin
   273 begin
   254 Me:= Me; // avoid compiler hint
   274 Me:= Me; // avoid compiler hint
   255 rate:= 0;
   275 rate:= 0;
   256 for i:= 0 to Pred(Targets.Count) do
   276 for i:= 0 to Pred(Targets.Count) do
   257     with Targets.ar[i] do
   277     with Targets.ar[i] do
   258          begin
   278         begin
   259          dmg:= r - hwRound(DistanceI(Point.x - x, Point.y - y));
   279         dmg:= r - hwRound(DistanceI(Point.x - x, Point.y - y));
   260          dmg:= hwRound(_0_01 * cDamageModifier * dmg * cDamagePercent);
   280         dmg:= hwRound(_0_01 * cDamageModifier * dmg * cDamagePercent);
   261          if dmg > 0 then
   281         if dmg > 0 then
   262             begin
   282             begin
   263             if power >= abs(Score) then
   283             if power >= abs(Score) then
   264                if Score > 0 then inc(rate, KillScore)
   284                 if Score > 0 then
   265                             else dec(rate, KillScore * friendlyfactor div 100)
   285                     inc(rate, KillScore)
       
   286                 else
       
   287                     dec(rate, KillScore * friendlyfactor div 100)
   266             else
   288             else
   267                if Score > 0 then inc(rate, power)
   289                 if Score > 0 then
   268                             else dec(rate, power * friendlyfactor div 100)
   290                     inc(rate, power)
       
   291                 else
       
   292                     dec(rate, power * friendlyfactor div 100)
   269             end;
   293             end;
   270          end;
   294         end;
   271 RateShove:= rate * 1024
   295 RateShove:= rate * 1024
   272 end;
   296 end;
   273 
   297 
   274 function RateShotgun(Me: PGear; x, y: LongInt): LongInt;
   298 function RateShotgun(Me: PGear; x, y: LongInt): LongInt;
   275 var i, dmg, rate: LongInt;
   299 var i, dmg, rate: LongInt;
   276 begin
   300 begin
   277 rate:= 0;
   301 rate:= 0;
   278 // add our virtual position
   302 // add our virtual position
   279 with Targets.ar[Targets.Count] do
   303 with Targets.ar[Targets.Count] do
   280      begin
   304     begin
   281      Point.x:= hwRound(Me^.X);
   305     Point.x:= hwRound(Me^.X);
   282      Point.y:= hwRound(Me^.Y);
   306     Point.y:= hwRound(Me^.Y);
   283      Score:= - ThinkingHH^.Health
   307     Score:= - ThinkingHH^.Health
   284      end;
   308     end;
   285 // rate shot
   309 // rate shot
   286 for i:= 0 to Targets.Count do
   310 for i:= 0 to Targets.Count do
   287     with Targets.ar[i] do
   311     with Targets.ar[i] do
   288          begin
   312         begin
   289          dmg:= min(cHHRadius + cShotgunRadius + 4 - hwRound(DistanceI(Point.x - x, Point.y - y)), 25);
   313         dmg:= min(cHHRadius + cShotgunRadius + 4 - hwRound(DistanceI(Point.x - x, Point.y - y)), 25);
   290          dmg:= hwRound(_0_01 * cDamageModifier * dmg * cDamagePercent);
   314         dmg:= hwRound(_0_01 * cDamageModifier * dmg * cDamagePercent);
   291          if dmg > 0 then
   315         if dmg > 0 then
   292             begin
   316             begin
   293                 if dmg >= abs(Score) then dmg := KillScore;
   317                 if dmg >= abs(Score) then
   294                 if Score > 0 then inc(rate, dmg)
   318                     dmg := KillScore;
   295                 else dec(rate, dmg * friendlyfactor div 100);
   319                 if Score > 0 then
       
   320                     inc(rate, dmg)
       
   321                 else
       
   322                     dec(rate, dmg * friendlyfactor div 100);
   296             end;
   323             end;
   297          end;        
   324         end;        
   298 RateShotgun:= rate * 1024;
   325 RateShotgun:= rate * 1024;
   299 end;
   326 end;
   300 
   327 
   301 function RateHammer(Me: PGear): LongInt;
   328 function RateHammer(Me: PGear): LongInt;
   302 var x, y, i, r, rate: LongInt;
   329 var x, y, i, r, rate: LongInt;
   306 y:= hwRound(Me^.Y);
   333 y:= hwRound(Me^.Y);
   307 rate:= 0;
   334 rate:= 0;
   308 
   335 
   309 for i:= 0 to Pred(Targets.Count) do
   336 for i:= 0 to Pred(Targets.Count) do
   310     with Targets.ar[i] do
   337     with Targets.ar[i] do
   311          begin
   338         begin
   312          // hammer hit radius is 8, shift is 10
   339          // hammer hit radius is 8, shift is 10
   313          r:= hwRound(DistanceI(Point.x - x, Point.y - y));
   340         r:= hwRound(DistanceI(Point.x - x, Point.y - y));
   314 
   341 
   315          if r <= 18 then
   342         if r <= 18 then
   316             if Score > 0 then 
   343             if Score > 0 then 
   317                 inc(rate, Score div 3)
   344                 inc(rate, Score div 3)
   318                 else 
   345             else 
   319                 inc(rate, Score div 3 * friendlyfactor div 100)
   346                 inc(rate, Score div 3 * friendlyfactor div 100)
   320          end;
   347         end;
   321 RateHammer:= rate * 1024;
   348 RateHammer:= rate * 1024;
   322 end;
   349 end;
   323 
   350 
   324 function HHJump(Gear: PGear; JumpType: TJumpType; var GoInfo: TGoInfo): boolean;
   351 function HHJump(Gear: PGear; JumpType: TJumpType; var GoInfo: TGoInfo): boolean;
   325 var bX, bY: LongInt;
   352 var bX, bY: LongInt;
   329 GoInfo.Ticks:= 0;
   356 GoInfo.Ticks:= 0;
   330 GoInfo.JumpType:= jmpNone;
   357 GoInfo.JumpType:= jmpNone;
   331 bX:= hwRound(Gear^.X);
   358 bX:= hwRound(Gear^.X);
   332 bY:= hwRound(Gear^.Y);
   359 bY:= hwRound(Gear^.Y);
   333 case JumpType of
   360 case JumpType of
   334      jmpNone: exit(bRes);
   361     jmpNone:
   335     jmpHJump: if TestCollisionYwithGear(Gear, -1) = 0 then
   362     exit(bRes);
   336                  begin
   363     
   337                  Gear^.dY:= -_0_2;
   364     jmpHJump:
   338                  SetLittle(Gear^.dX);
   365     if TestCollisionYwithGear(Gear, -1) = 0 then
   339                  Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
   366         begin
   340                  end else exit(bRes);
   367         Gear^.dY:= -_0_2;
   341     jmpLJump: begin
   368         SetLittle(Gear^.dX);
   342               if TestCollisionYwithGear(Gear, -1) <> 0 then
   369         Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
   343                  if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - int2hwFloat(2) else
   370         end
   344                  if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - _1;
   371     else
   345               if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
   372         exit(bRes);
   346                  or   (TestCollisionYwithGear(Gear, -1) <> 0)) then
   373         
   347                  begin
   374     jmpLJump:
   348                  Gear^.dY:= -_0_15;
   375     begin
   349                  Gear^.dX:= SignAs(_0_15, Gear^.dX);
   376     if TestCollisionYwithGear(Gear, -1) <> 0 then
   350                  Gear^.State:= Gear^.State or gstMoving or gstHHJumping
   377           if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
   351                  end else exit(bRes)
   378             Gear^.Y:= Gear^.Y - int2hwFloat(2)
   352               end
   379         else
       
   380             if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then
       
   381                 Gear^.Y:= Gear^.Y - _1;
       
   382         if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
       
   383         or (TestCollisionYwithGear(Gear, -1) <> 0)) then
       
   384             begin
       
   385             Gear^.dY:= -_0_15;
       
   386             Gear^.dX:= SignAs(_0_15, Gear^.dX);
       
   387             Gear^.State:= Gear^.State or gstMoving or gstHHJumping
       
   388             end
       
   389         else
       
   390             exit(bRes)
       
   391     end
   353     end;
   392     end;
   354 
   393 
   355 repeat
   394 repeat
   356 if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then exit(bRes);
   395     if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then
   357 if (Gear^.State and gstMoving) <> 0 then
   396         exit(bRes);
   358    begin
   397     if (Gear^.State and gstMoving) <> 0 then
   359    if (GoInfo.Ticks = 350) then
   398         begin
   360       if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
   399         if (GoInfo.Ticks = 350) then
   361          begin
   400             if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
   362          Gear^.dY:= -_0_25;
   401                 begin
   363          Gear^.dX:= SignAs(_0_02, Gear^.dX)
   402                 Gear^.dY:= -_0_25;
   364          end;
   403                 Gear^.dX:= SignAs(_0_02, Gear^.dX)
   365    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
   404                 end;
   366    Gear^.X:= Gear^.X + Gear^.dX;
   405     if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
   367    inc(GoInfo.Ticks);
   406         Gear^.X:= Gear^.X + Gear^.dX;
   368    Gear^.dY:= Gear^.dY + cGravity;
   407     inc(GoInfo.Ticks);
   369    if Gear^.dY > _0_4 then exit(bRes);
   408     Gear^.dY:= Gear^.dY + cGravity;
   370    if (Gear^.dY.isNegative)and (TestCollisionYwithGear(Gear, -1) <> 0) then Gear^.dY:= _0;
   409     if Gear^.dY > _0_4 then
   371    Gear^.Y:= Gear^.Y + Gear^.dY;
   410         exit(bRes);
   372    if (not Gear^.dY.isNegative)and (TestCollisionYwithGear(Gear, 1) <> 0) then
   411     if (Gear^.dY.isNegative)and (TestCollisionYwithGear(Gear, -1) <> 0) then
   373       begin
   412         Gear^.dY:= _0;
   374       Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   413     Gear^.Y:= Gear^.Y + Gear^.dY;
   375       Gear^.dY:= _0;
   414     if (not Gear^.dY.isNegative)and (TestCollisionYwithGear(Gear, 1) <> 0) then
   376       case JumpType of
   415         begin
   377            jmpHJump: if bY - hwRound(Gear^.Y) > 5 then
   416         Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   378                         begin
   417         Gear^.dY:= _0;
   379                         bRes:= true;
   418         case JumpType of
   380                         GoInfo.JumpType:= jmpHJump;
   419             jmpHJump:
   381                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   420             if bY - hwRound(Gear^.Y) > 5 then
   382                         end;
   421                 begin
   383            jmpLJump: if abs(bX - hwRound(Gear^.X)) > 30 then
   422                 bRes:= true;
   384                         begin
   423                 GoInfo.JumpType:= jmpHJump;
   385                         bRes:= true;
   424                 inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   386                         GoInfo.JumpType:= jmpLJump;
   425                 end;
   387                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   426             jmpLJump: if abs(bX - hwRound(Gear^.X)) > 30 then
   388                         end;
   427                 begin
   389            end;
   428                 bRes:= true;
   390       exit(bRes)
   429                 GoInfo.JumpType:= jmpLJump;
   391       end;
   430                 inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   392    end;
   431                 end
       
   432                 end;
       
   433             exit(bRes)
       
   434             end;
       
   435         end;
   393 until false
   436 until false
   394 end;
   437 end;
   395 
   438 
   396 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
   439 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
   397 var pX, pY: LongInt;
   440 var pX, pY: LongInt;
   402 GoInfo.FallPix:= 0;
   445 GoInfo.FallPix:= 0;
   403 GoInfo.JumpType:= jmpNone;
   446 GoInfo.JumpType:= jmpNone;
   404 repeat
   447 repeat
   405 pX:= hwRound(Gear^.X);
   448 pX:= hwRound(Gear^.X);
   406 pY:= hwRound(Gear^.Y);
   449 pY:= hwRound(Gear^.Y);
   407 if pY + cHHRadius >= cWaterLine then exit(false);
   450 if pY + cHHRadius >= cWaterLine then
       
   451     exit(false);
   408 if (Gear^.State and gstMoving) <> 0 then
   452 if (Gear^.State and gstMoving) <> 0 then
   409    begin
   453     begin
   410    inc(GoInfo.Ticks);
   454     inc(GoInfo.Ticks);
   411    Gear^.dY:= Gear^.dY + cGravity;
   455     Gear^.dY:= Gear^.dY + cGravity;
   412    if Gear^.dY > _0_4 then
   456     if Gear^.dY > _0_4 then
   413       begin
   457         begin
   414       Goinfo.FallPix:= 0;
   458         Goinfo.FallPix:= 0;
   415       HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall with damage
   459         HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall with damage
   416       exit(false)
   460         exit(false)
   417       end;
   461         end;
   418    Gear^.Y:= Gear^.Y + Gear^.dY;
   462     Gear^.Y:= Gear^.Y + Gear^.dY;
   419    if hwRound(Gear^.Y) > pY then inc(GoInfo.FallPix);
   463     if hwRound(Gear^.Y) > pY then
   420    if TestCollisionYwithGear(Gear, 1) <> 0 then
   464         inc(GoInfo.FallPix);
   421       begin
   465     if TestCollisionYwithGear(Gear, 1) <> 0 then
   422       inc(GoInfo.Ticks, 410);
   466         begin
   423       Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   467         inc(GoInfo.Ticks, 410);
   424       Gear^.dY:= _0;
   468         Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   425       HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall
   469         Gear^.dY:= _0;
   426       exit(true)
   470         HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall
   427       end;
   471         exit(true)
   428    continue
   472         end;
   429    end;
   473     continue
   430    if (Gear^.Message and gmLeft  )<>0 then Gear^.dX:= -cLittle else
   474     end;
   431    if (Gear^.Message and gmRight )<>0 then Gear^.dX:=  cLittle else exit(false);
   475     if (Gear^.Message and gmLeft  )<>0 then
   432    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   476         Gear^.dX:= -cLittle
   433       begin
   477     else
   434       if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
   478         if (Gear^.Message and gmRight )<>0 then
   435          or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
   479              Gear^.dX:=  cLittle
   436       if not (TestCollisionXwithXYShift(Gear, _0, -5, hwSign(Gear^.dX))
   480         else
   437          or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
   481                 exit(false);
   438       if not (TestCollisionXwithXYShift(Gear, _0, -4, hwSign(Gear^.dX))
   482     if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   439          or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
   483         begin
   440       if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
   484         if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
   441          or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
   485         or (TestCollisionYwithGear(Gear, -1) <> 0)) then
   442       if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
   486             Gear^.Y:= Gear^.Y - _1;
   443          or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
   487             
   444       if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
   488         if not (TestCollisionXwithXYShift(Gear, _0, -5, hwSign(Gear^.dX))
   445          or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
   489         or (TestCollisionYwithGear(Gear, -1) <> 0)) then
   446       end;
   490             Gear^.Y:= Gear^.Y - _1;
   447 
   491             
   448    if not TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   492         if not (TestCollisionXwithXYShift(Gear, _0, -4, hwSign(Gear^.dX))
   449       begin
   493         or (TestCollisionYwithGear(Gear, -1) <> 0)) then
   450       Gear^.X:= Gear^.X + int2hwFloat(hwSign(Gear^.dX));
   494             Gear^.Y:= Gear^.Y - _1;
   451       inc(GoInfo.Ticks, cHHStepTicks)
   495             
   452       end;
   496         if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
   453    if TestCollisionYwithGear(Gear, 1) = 0 then
   497         or (TestCollisionYwithGear(Gear, -1) <> 0)) then
   454    begin
   498             Gear^.Y:= Gear^.Y - _1;
   455    Gear^.Y:= Gear^.Y + _1;
   499         if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
   456    if TestCollisionYwithGear(Gear, 1) = 0 then
   500         or (TestCollisionYwithGear(Gear, -1) <> 0)) then
   457    begin
   501             Gear^.Y:= Gear^.Y - _1;
   458    Gear^.Y:= Gear^.Y + _1;
   502             
   459    if TestCollisionYwithGear(Gear, 1) = 0 then
   503         if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
   460    begin
   504         or (TestCollisionYwithGear(Gear, -1) <> 0)) then
   461    Gear^.Y:= Gear^.Y + _1;
   505             Gear^.Y:= Gear^.Y - _1;
   462    if TestCollisionYwithGear(Gear, 1) = 0 then
   506         end;
   463    begin
   507 
   464    Gear^.Y:= Gear^.Y + _1;
   508     if not TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   465    if TestCollisionYwithGear(Gear, 1) = 0 then
   509         begin
   466    begin
   510         Gear^.X:= Gear^.X + int2hwFloat(hwSign(Gear^.dX));
   467    Gear^.Y:= Gear^.Y + _1;
   511         inc(GoInfo.Ticks, cHHStepTicks)
   468    if TestCollisionYwithGear(Gear, 1) = 0 then
   512         end;
   469    begin
   513         
   470    Gear^.Y:= Gear^.Y + _1;
   514     if TestCollisionYwithGear(Gear, 1) = 0 then
   471    if TestCollisionYwithGear(Gear, 1) = 0 then
   515         begin
   472       begin
   516         Gear^.Y:= Gear^.Y + _1;
   473       Gear^.Y:= Gear^.Y - _6;
   517         
   474       Gear^.dY:= _0;
   518     if TestCollisionYwithGear(Gear, 1) = 0 then
   475       Gear^.State:= Gear^.State or gstMoving
   519           begin
   476       end
   520         Gear^.Y:= Gear^.Y + _1;
   477    end
   521         
   478    end
   522     if TestCollisionYwithGear(Gear, 1) = 0 then
   479    end
   523         begin
   480    end
   524         Gear^.Y:= Gear^.Y + _1;
   481    end
   525 
   482    end;
   526     if TestCollisionYwithGear(Gear, 1) = 0 then
       
   527         begin
       
   528         Gear^.Y:= Gear^.Y + _1;
       
   529 
       
   530     if TestCollisionYwithGear(Gear, 1) = 0 then
       
   531         begin
       
   532         Gear^.Y:= Gear^.Y + _1;
       
   533 
       
   534     if TestCollisionYwithGear(Gear, 1) = 0 then
       
   535         begin
       
   536         Gear^.Y:= Gear^.Y + _1;
       
   537 
       
   538     if TestCollisionYwithGear(Gear, 1) = 0 then
       
   539         begin
       
   540         Gear^.Y:= Gear^.Y - _6;
       
   541         Gear^.dY:= _0;
       
   542         Gear^.State:= Gear^.State or gstMoving
       
   543         end
       
   544     end
       
   545     end
       
   546     end
       
   547     end
       
   548     end
       
   549     end;
   483 if (pX <> hwRound(Gear^.X)) and ((Gear^.State and gstMoving) = 0) then
   550 if (pX <> hwRound(Gear^.X)) and ((Gear^.State and gstMoving) = 0) then
   484    exit(true);
   551     exit(true);
   485 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0);
   552 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0);
   486 HHJump(AltGear, jmpHJump, GoInfo);
   553 HHJump(AltGear, jmpHJump, GoInfo);
   487 HHGo:= false;
   554 HHGo:= false;
   488 end;
   555 end;
   489 
   556 
   490 function AIrndSign(num: LongInt): LongInt;
   557 function AIrndSign(num: LongInt): LongInt;
   491 begin
   558 begin
   492 if random(2) = 0 then AIrndSign:=   num
   559 if random(2) = 0 then
   493                  else AIrndSign:= - num
   560     AIrndSign:=   num
       
   561 else
       
   562     AIrndSign:= - num
   494 end;
   563 end;
   495 
   564 
   496 procedure initModule;
   565 procedure initModule;
   497 begin
   566 begin
   498     friendlyfactor:= 300;
   567     friendlyfactor:= 300;