hedgewars/uAIMisc.pas
changeset 369 2aed85310727
parent 351 29bc9c36ad5f
child 370 c75410fe3133
equal deleted inserted replaced
368:fe71e55d2d7b 369:2aed85310727
    18 
    18 
    19 unit uAIMisc;
    19 unit uAIMisc;
    20 interface
    20 interface
    21 uses SDLh, uConsts, uGears, uFloat;
    21 uses SDLh, uConsts, uGears, uFloat;
    22 {$INCLUDE options.inc}
    22 {$INCLUDE options.inc}
    23  {
    23 
    24 type TTarget = record
    24 type TTarget = record
    25                Point: TPoint;
    25                Point: TPoint;
    26                Score: integer;
    26                Score: integer;
    27                end;
    27                end;
    28      TTargets = record
    28      TTargets = record
    41 procedure AwareOfExplosion(x, y, r: integer);
    41 procedure AwareOfExplosion(x, y, r: integer);
    42 function RatePlace(Gear: PGear): integer;
    42 function RatePlace(Gear: PGear): integer;
    43 function TestColl(x, y, r: integer): boolean;
    43 function TestColl(x, y, r: integer): boolean;
    44 function RateExplosion(Me: PGear; x, y, r: integer): integer;
    44 function RateExplosion(Me: PGear; x, y, r: integer): integer;
    45 function RateShove(Me: PGear; x, y, r, power: integer): integer;
    45 function RateShove(Me: PGear; x, y, r, power: integer): integer;
    46 function HHGo(Gear, AltGear: PGear; out GoInfo: TGoInfo): boolean;
    46 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
    47 function rndSign(num: integer): integer;
    47 //function rndSign(num: integer): integer;
    48 
    48 
    49 var ThinkingHH: PGear;
    49 var ThinkingHH: PGear;
    50     Targets: TTargets;
    50     Targets: TTargets;
    51                        }
    51                        
    52 implementation
    52 implementation
    53 {uses uTeams, uMisc, uLand, uCollisions;
    53 uses uTeams, uMisc, uLand, uCollisions;
    54 const KillScore = 200;
    54 const KillScore = 200;
    55       MAXBONUS = 1024;
    55       MAXBONUS = 1024;
    56       
    56 
    57 type TBonus = record
    57 type TBonus = record
    58               X, Y: integer;
    58               X, Y: integer;
    59               Radius: integer;
    59               Radius: integer;
    60               Score: integer;
    60               Score: integer;
    61               end;
    61               end;
    74 Targets.Count:= 0;
    74 Targets.Count:= 0;
    75 t:= TeamsList;
    75 t:= TeamsList;
    76 while t <> nil do
    76 while t <> nil do
    77       begin
    77       begin
    78       for i:= 0 to cMaxHHIndex do
    78       for i:= 0 to cMaxHHIndex do
    79           if (t.Hedgehogs[i].Gear <> nil)
    79           if (t^.Hedgehogs[i].Gear <> nil)
    80              and (t.Hedgehogs[i].Gear <> ThinkingHH) then
    80              and (t^.Hedgehogs[i].Gear <> ThinkingHH) then
    81              begin
    81              begin
    82              with Targets.ar[Targets.Count], t.Hedgehogs[i] do
    82              with Targets.ar[Targets.Count], t^.Hedgehogs[i] do
    83                   begin
    83                   begin
    84                   Point.X:= Round(Gear.X);
    84                   Point.X:= hwRound(Gear^.X);
    85                   Point.Y:= Round(Gear.Y);
    85                   Point.Y:= hwRound(Gear^.Y);
    86                   if t.Color <> CurrentTeam.Color then Score:=  Gear.Health
    86                   if t^.Color <> CurrentTeam^.Color then Score:=  Gear^.Health
    87                                                   else Score:= -Gear.Health
    87                                                     else Score:= -Gear^.Health
    88                   end;
    88                   end;
    89              inc(Targets.Count)
    89              inc(Targets.Count)
    90              end;
    90              end;
    91       t:= t.Next
    91       t:= t^.Next
    92       end
    92       end
    93 end;
    93 end;
    94 
    94 
    95 procedure FillBonuses(isAfterAttack: boolean);
    95 procedure FillBonuses(isAfterAttack: boolean);
    96 var Gear: PGear;
    96 var Gear: PGear;
   106     TryDo(bonuses.Count <= MAXBONUS, 'Bonuses overflow', true)
   106     TryDo(bonuses.Count <= MAXBONUS, 'Bonuses overflow', true)
   107     end;
   107     end;
   108 
   108 
   109 begin
   109 begin
   110 bonuses.Count:= 0;
   110 bonuses.Count:= 0;
   111 MyColor:= PHedgehog(ThinkingHH.Hedgehog).Team.Color;
   111 MyColor:= PHedgehog(ThinkingHH^.Hedgehog)^.Team^.Color;
   112 Gear:= GearsList;
   112 Gear:= GearsList;
   113 while Gear <> nil do
   113 while Gear <> nil do
   114       begin
   114       begin
   115       case Gear.Kind of
   115       case Gear^.Kind of
   116            gtCase: AddBonus(round(Gear.X), round(Gear.Y), 33, 25);
   116            gtCase: AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 33, 25);
   117            gtMine: if (Gear.State and gstAttacking) = 0 then AddBonus(round(Gear.X), round(Gear.Y), 50, -50)
   117            gtMine: if (Gear^.State and gstAttacking) = 0 then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -50)
   118                                                         else AddBonus(round(Gear.X), round(Gear.Y), 100, -50); // mine is on
   118                                                         else AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, -50); // mine is on
   119            gtDynamite: AddBonus(round(Gear.X), round(Gear.Y), 150, -75);
   119            gtDynamite: AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -75);
   120            gtHedgehog: begin
   120            gtHedgehog: begin
   121                        if Gear.Damage >= Gear.Health then AddBonus(round(Gear.X), round(Gear.Y), 60, -25) else
   121                        if Gear^.Damage >= Gear^.Health then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 60, -25) else
   122                           if isAfterAttack and (ThinkingHH.Hedgehog <> Gear.Hedgehog) then
   122                           if isAfterAttack and (ThinkingHH^.Hedgehog <> Gear^.Hedgehog) then
   123                              if (MyColor = PHedgehog(Gear.Hedgehog).Team.Color) then AddBonus(round(Gear.X), round(Gear.Y), 150, -3) // hedgehog-friend
   123                              if (MyColor = PHedgehog(Gear^.Hedgehog)^.Team^.Color) then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -3) // hedgehog-friend
   124                                                                                 else AddBonus(round(Gear.X), round(Gear.Y), 100, 3)
   124                                                                                    else AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, 3)
   125                        end;
   125                        end;
   126            end;
   126            end;
   127       Gear:= Gear.NextGear
   127       Gear:= Gear^.NextGear
   128       end;
   128       end;
   129 if isAfterAttack and (KnownExplosion.Radius > 0) then
   129 if isAfterAttack and (KnownExplosion.Radius > 0) then
   130    with KnownExplosion do
   130    with KnownExplosion do
   131         AddBonus(X, Y, Radius + 10, -Radius);
   131         AddBonus(X, Y, Radius + 10, -Radius);
   132 end;
   132 end;
   138 KnownExplosion.Radius:= r
   138 KnownExplosion.Radius:= r
   139 end;
   139 end;
   140 
   140 
   141 function RatePlace(Gear: PGear): integer;
   141 function RatePlace(Gear: PGear): integer;
   142 var i, r: integer;
   142 var i, r: integer;
       
   143     Result: integer;
   143 begin
   144 begin
   144 Result:= 0;
   145 Result:= 0;
   145 for i:= 0 to Pred(bonuses.Count) do
   146 for i:= 0 to Pred(bonuses.Count) do
   146     with bonuses.ar[i] do
   147     with bonuses.ar[i] do
   147          begin
   148          begin
   148          r:= round(sqrt(sqr(Gear.X - X) + sqr(Gear.Y - y)));
   149          r:= hwRound(Distance(Gear^.X - X, Gear^.Y - y));
   149          if r < Radius then
   150          if r < Radius then
   150             inc(Result, Score * (Radius - r))
   151             inc(Result, Score * (Radius - r))
   151          end;
   152          end;
       
   153     RatePlace:= Result
   152 end;
   154 end;
   153 
   155 
   154 function TestColl(x, y, r: integer): boolean;
   156 function TestColl(x, y, r: integer): boolean;
   155 begin
   157 var b: boolean;
   156 Result:=(((x-r) and $FFFFF800) = 0)and(((y-r) and $FFFFFC00) = 0) and (Land[y-r, x-r] <> 0);
   158 begin
   157 if Result then exit;
   159 b:= (((x-r) and $FFFFF800) = 0)and(((y-r) and $FFFFFC00) = 0) and (Land[y-r, x-r] <> 0);
   158 Result:=(((x-r) and $FFFFF800) = 0)and(((y+r) and $FFFFFC00) = 0) and (Land[y+r, x-r] <> 0);
   160 if b then exit(true);
   159 if Result then exit;
   161 b:=(((x-r) and $FFFFF800) = 0)and(((y+r) and $FFFFFC00) = 0) and (Land[y+r, x-r] <> 0);
   160 Result:=(((x+r) and $FFFFF800) = 0)and(((y-r) and $FFFFFC00) = 0) and (Land[y-r, x+r] <> 0);
   162 if b then exit(true);
   161 if Result then exit;
   163 b:=(((x+r) and $FFFFF800) = 0)and(((y-r) and $FFFFFC00) = 0) and (Land[y-r, x+r] <> 0);
   162 Result:=(((x+r) and $FFFFF800) = 0)and(((y+r) and $FFFFFC00) = 0) and (Land[y+r, x+r] <> 0);
   164 if b then exit(true);
       
   165 TestColl:=(((x+r) and $FFFFF800) = 0)and(((y+r) and $FFFFFC00) = 0) and (Land[y+r, x+r] <> 0)
   163 end;
   166 end;
   164 
   167 
   165 function RateExplosion(Me: PGear; x, y, r: integer): integer;
   168 function RateExplosion(Me: PGear; x, y, r: integer): integer;
   166 var i, dmg: integer;
   169 var i, dmg, Result: integer;
   167 begin
   170 begin
   168 Result:= 0;
   171 Result:= 0;
   169 // add our virtual position
   172 // add our virtual position
   170 with Targets.ar[Targets.Count] do
   173 with Targets.ar[Targets.Count] do
   171      begin
   174      begin
   172      Point.x:= round(Me.X);
   175      Point.x:= hwRound(Me^.X);
   173      Point.y:= round(Me.Y);
   176      Point.y:= hwRound(Me^.Y);
   174      Score:= - ThinkingHH.Health
   177      Score:= - ThinkingHH^.Health
   175      end;
   178      end;
   176 // rate explosion
   179 // rate explosion
   177 for i:= 0 to Targets.Count do
   180 for i:= 0 to Targets.Count do
   178     with Targets.ar[i] do
   181     with Targets.ar[i] do
   179          begin
   182          begin
   180          dmg:= r - Round(sqrt(sqr(Point.x - x) + sqr(Point.y - y)));
   183          dmg:= r - hwRound(Distance(Point.x - x, Point.y - y));
   181          if dmg > 0 then
   184          if dmg > 0 then
   182             begin
   185             begin
   183             dmg:= dmg shr 1;
   186             dmg:= dmg shr 1;
   184             if dmg > abs(Score) then
   187             if dmg > abs(Score) then
   185                if Score > 0 then inc(Result, KillScore)
   188                if Score > 0 then inc(Result, KillScore)
   187             else
   190             else
   188                if Score > 0 then inc(Result, dmg)
   191                if Score > 0 then inc(Result, dmg)
   189                             else dec(Result, dmg * 3)
   192                             else dec(Result, dmg * 3)
   190             end;
   193             end;
   191          end;
   194          end;
   192 Result:= Result * 1024
   195 RateExplosion:= Result * 1024
   193 end;
   196 end;
   194 
   197 
   195 function RateShove(Me: PGear; x, y, r, power: integer): integer;
   198 function RateShove(Me: PGear; x, y, r, power: integer): integer;
   196 var i, dmg: integer;
   199 var i, dmg, Result: integer;
   197 begin
   200 begin
   198 Result:= 0;
   201 Result:= 0;
   199 for i:= 0 to Targets.Count do
   202 for i:= 0 to Targets.Count do
   200     with Targets.ar[i] do
   203     with Targets.ar[i] do
   201          begin
   204          begin
   202          dmg:= r - Round(sqrt(sqr(Point.x - x) + sqr(Point.y - y)));
   205          dmg:= r - hwRound(Distance(Point.x - x, Point.y - y));
   203          if dmg > 0 then
   206          if dmg > 0 then
   204             begin
   207             begin
   205             if power > abs(Score) then
   208             if power > abs(Score) then
   206                if Score > 0 then inc(Result, KillScore)
   209                if Score > 0 then inc(Result, KillScore)
   207                             else dec(Result, KillScore * 3)
   210                             else dec(Result, KillScore * 3)
   208             else
   211             else
   209                if Score > 0 then inc(Result, power)
   212                if Score > 0 then inc(Result, power)
   210                             else dec(Result, power * 3)
   213                             else dec(Result, power * 3)
   211             end;
   214             end;
   212          end;
   215          end;
   213 Result:= Result * 1024
   216 RateShove:= Result * 1024
   214 end;
   217 end;
   215 
   218 
   216 function HHJump(Gear: PGear; JumpType: TJumpType; out GoInfo: TGoInfo): boolean;
   219 function HHJump(Gear: PGear; JumpType: TJumpType; var GoInfo: TGoInfo): boolean;
   217 var bX, bY: integer;
   220 var bX, bY: integer;
       
   221     Result: boolean;
   218 begin
   222 begin
   219 Result:= false;
   223 Result:= false;
   220 GoInfo.Ticks:= 0;
   224 GoInfo.Ticks:= 0;
   221 GoInfo.FallPix:= 0;
   225 GoInfo.FallPix:= 0;
   222 GoInfo.JumpType:= jmpNone;
   226 GoInfo.JumpType:= jmpNone;
   223 bX:= round(Gear.X);
   227 bX:= hwRound(Gear^.X);
   224 bY:= round(Gear.Y);
   228 bY:= hwRound(Gear^.Y);
   225 case JumpType of
   229 case JumpType of
   226      jmpNone: exit;
   230      jmpNone: exit(Result);
   227     jmpHJump: if not TestCollisionYwithGear(Gear, -1) then
   231     jmpHJump: if not TestCollisionYwithGear(Gear, -1) then
   228                  begin
   232                  begin
   229                  Gear.dY:= -0.20;
   233                  Gear^.dY:= -_0_2;
   230                  Gear.dX:= 0.0000001 * hwSign(Gear.dX);
   234                  SetLittle(Gear^.dX);
   231                  Gear.X:= Gear.X - hwSign(Gear.dX)*0.00008; // shift compensation
   235                  Gear^.State:= Gear^.State or gstFalling or gstHHJumping;
   232                  Gear.State:= Gear.State or gstFalling or gstHHJumping;
   236                  end else exit(Result);
   233                  end else exit;
       
   234     jmpLJump: begin
   237     jmpLJump: begin
   235               if not TestCollisionYwithGear(Gear, -1) then
   238               if not TestCollisionYwithGear(Gear, -1) then
   236                  if not TestCollisionXwithXYShift(Gear, 0, -2, hwSign(Gear.dX)) then Gear.Y:= Gear.Y - 2 else
   239                  if not TestCollisionXwithXYShift(Gear, 0, -2, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - 2 else
   237                  if not TestCollisionXwithXYShift(Gear, 0, -1, hwSign(Gear.dX)) then Gear.Y:= Gear.Y - 1;
   240                  if not TestCollisionXwithXYShift(Gear, 0, -1, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - 1;
   238               if not (TestCollisionXwithGear(Gear, hwSign(Gear.dX))
   241               if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
   239                  or   TestCollisionYwithGear(Gear, -1)) then
   242                  or   TestCollisionYwithGear(Gear, -1)) then
   240                  begin
   243                  begin
   241                  Gear.dY:= -0.15;
   244                  Gear^.dY:= _0_15;
   242                  Gear.dX:= hwSign(Gear.dX) * 0.15;
   245                  Gear^.dX:= hwSign(Gear^.dX) * _0_15;
   243                  Gear.State:= Gear.State or gstFalling or gstHHJumping
   246                  Gear^.State:= Gear^.State or gstFalling or gstHHJumping
   244                  end else exit
   247                  end else exit(Result)
   245               end
   248               end
   246     end;
   249     end;
   247     
   250     
   248 repeat
   251 repeat
   249 if Gear.Y + cHHRadius >= cWaterLine then exit;
   252 if not (Gear^.Y + cHHRadius < cWaterLine) then exit(Result);
   250 if (Gear.State and gstFalling) <> 0 then
   253 if (Gear^.State and gstFalling) <> 0 then
   251    begin
   254    begin
   252    if (GoInfo.Ticks = 350) then
   255    if (GoInfo.Ticks = 350) then
   253       if (abs(Gear.dX) < 0.0000002) and (Gear.dY < -0.02) then
   256       if (hwAbs(Gear^.dX) < cLittle + cLittle) and (Gear^.dY < -_0_02) then
   254          begin
   257          begin
   255          Gear.dY:= -0.25;
   258          Gear^.dY:= -_0_25;
   256          Gear.dX:= hwSign(Gear.dX) * 0.02
   259          Gear^.dX:= hwSign(Gear^.dX) * _0_02
   257          end;
   260          end;
   258    if TestCollisionXwithGear(Gear, hwSign(Gear.dX)) then Gear.dX:= 0.0000001 * hwSign(Gear.dX);
   261    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
   259    Gear.X:= Gear.X + Gear.dX;
   262    Gear^.X:= Gear^.X + Gear^.dX;
   260    inc(GoInfo.Ticks);
   263    inc(GoInfo.Ticks);
   261    Gear.dY:= Gear.dY + cGravity;
   264    Gear^.dY:= Gear^.dY + cGravity;
   262    if Gear.dY > 0.40 then exit;
   265    if Gear^.dY > _0_4 then exit(Result);
   263    if (Gear.dY < 0)and TestCollisionYwithGear(Gear, -1) then Gear.dY:= 0; 
   266    if (Gear^.dY.isNegative)and TestCollisionYwithGear(Gear, -1) then Gear^.dY:= 0;
   264    Gear.Y:= Gear.Y + Gear.dY;
   267    Gear^.Y:= Gear^.Y + Gear^.dY;
   265    if (Gear.dY >= 0)and TestCollisionYwithGear(Gear, 1) then
   268    if (not Gear^.dY.isNegative)and TestCollisionYwithGear(Gear, 1) then
   266       begin
   269       begin
   267       Gear.State:= Gear.State and not (gstFalling or gstHHJumping);
   270       Gear^.State:= Gear^.State and not (gstFalling or gstHHJumping);
   268       Gear.dY:= 0;
   271       Gear^.dY:= 0;
   269       case JumpType of
   272       case JumpType of
   270            jmpHJump: if (bY - Gear.Y > 5) then
   273            jmpHJump: if (bY - Gear^.Y > 5) then
   271                         begin
   274                         begin
   272                         Result:= true;
   275                         Result:= true;
   273                         GoInfo.JumpType:= jmpHJump;
   276                         GoInfo.JumpType:= jmpHJump;
   274                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   277                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   275                         end;
   278                         end;
   276            jmpLJump: if abs(bX - Gear.X) > 30 then
   279            jmpLJump: if hwAbs(bX - Gear^.X) > 30 then
   277                         begin
   280                         begin
   278                         Result:= true;
   281                         Result:= true;
   279                         GoInfo.JumpType:= jmpLJump;
   282                         GoInfo.JumpType:= jmpLJump;
   280                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   283                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   281                         end;
   284                         end;
   282            end;
   285            end;
   283       exit
   286       exit(Result)
   284       end;
   287       end;
   285    end;
   288    end;
   286 until false;
   289 until false
   287 end;
   290 end;
   288 
   291 
   289 function HHGo(Gear, AltGear: PGear; out GoInfo: TGoInfo): boolean;
   292 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
   290 var pX, pY: integer;
   293 var pX, pY: integer;
       
   294     Result: boolean;
   291 begin
   295 begin
   292 Result:= false;
   296 Result:= false;
   293 AltGear^:= Gear^;
   297 AltGear^:= Gear^;
   294 
   298 
   295 GoInfo.Ticks:= 0;
   299 GoInfo.Ticks:= 0;
   296 GoInfo.FallPix:= 0;
   300 GoInfo.FallPix:= 0;
   297 GoInfo.JumpType:= jmpNone;
   301 GoInfo.JumpType:= jmpNone;
   298 repeat
   302 repeat
   299 pX:= round(Gear.X);
   303 pX:= hwRound(Gear^.X);
   300 pY:= round(Gear.Y);
   304 pY:= hwRound(Gear^.Y);
   301 if pY + cHHRadius >= cWaterLine then exit;
   305 if pY + cHHRadius >= cWaterLine then exit;
   302 if (Gear.State and gstFalling) <> 0 then
   306 if (Gear^.State and gstFalling) <> 0 then
   303    begin
   307    begin
   304    inc(GoInfo.Ticks);
   308    inc(GoInfo.Ticks);
   305    Gear.dY:= Gear.dY + cGravity;
   309    Gear^.dY:= Gear^.dY + cGravity;
   306    if Gear.dY > 0.40 then
   310    if Gear^.dY > _0_4 then
   307       begin
   311       begin
   308       Goinfo.FallPix:= 0;
   312       Goinfo.FallPix:= 0;
   309       HHJump(AltGear, jmpLJump, GoInfo); // try ljump enstead of fall with damage
   313       HHJump(AltGear, jmpLJump, GoInfo); // try ljump enstead of fall with damage
   310       exit
   314       exit(Result)
   311       end;
   315       end;
   312    Gear.Y:= Gear.Y + Gear.dY;
   316    Gear^.Y:= Gear^.Y + Gear^.dY;
   313    if round(Gear.Y) > pY then inc(GoInfo.FallPix);
   317    if hwRound(Gear^.Y) > pY then inc(GoInfo.FallPix);
   314    if TestCollisionYwithGear(Gear, 1) then
   318    if TestCollisionYwithGear(Gear, 1) then
   315       begin
   319       begin
   316       inc(GoInfo.Ticks, 300);
   320       inc(GoInfo.Ticks, 300);
   317       Gear.State:= Gear.State and not (gstFalling or gstHHJumping);
   321       Gear^.State:= Gear^.State and not (gstFalling or gstHHJumping);
   318       Gear.dY:= 0;
   322       Gear^.dY:= 0;
   319       Result:= true;
   323       Result:= true;
   320       HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall
   324       HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall
   321       exit
   325       exit(Result)
   322       end;
   326       end;
   323    continue
   327    continue
   324    end;
   328    end;
   325    if (Gear.Message and gm_Left  )<>0 then Gear.dX:= -1.0 else
   329    if (Gear^.Message and gm_Left  )<>0 then Gear^.dX:= -cLittle else
   326    if (Gear.Message and gm_Right )<>0 then Gear.dX:=  1.0 else exit;
   330    if (Gear^.Message and gm_Right )<>0 then Gear^.dX:=  cLittle else exit(Result);
   327    if TestCollisionXwithGear(Gear, hwSign(Gear.dX)) then
   331    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   328       begin
   332       begin
   329       if not (TestCollisionXwithXYShift(Gear, 0, -6, hwSign(Gear.dX))
   333       if not (TestCollisionXwithXYShift(Gear, 0, -6, hwSign(Gear^.dX))
   330          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   334          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   331       if not (TestCollisionXwithXYShift(Gear, 0, -5, hwSign(Gear.dX))
   335       if not (TestCollisionXwithXYShift(Gear, 0, -5, hwSign(Gear^.dX))
   332          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   336          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   333       if not (TestCollisionXwithXYShift(Gear, 0, -4, hwSign(Gear.dX))
   337       if not (TestCollisionXwithXYShift(Gear, 0, -4, hwSign(Gear^.dX))
   334          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   338          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   335       if not (TestCollisionXwithXYShift(Gear, 0, -3, hwSign(Gear.dX))
   339       if not (TestCollisionXwithXYShift(Gear, 0, -3, hwSign(Gear^.dX))
   336          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   340          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   337       if not (TestCollisionXwithXYShift(Gear, 0, -2, hwSign(Gear.dX))
   341       if not (TestCollisionXwithXYShift(Gear, 0, -2, hwSign(Gear^.dX))
   338          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   342          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   339       if not (TestCollisionXwithXYShift(Gear, 0, -1, hwSign(Gear.dX))
   343       if not (TestCollisionXwithXYShift(Gear, 0, -1, hwSign(Gear^.dX))
   340          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   344          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   341       end;
   345       end;
   342 
   346 
   343    if not TestCollisionXwithGear(Gear, hwSign(Gear.dX)) then
   347    if not TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   344       begin
   348       begin
   345       Gear.X:= Gear.X + Gear.dX;
   349       Gear^.X:= Gear^.X + Gear^.dX;
   346       inc(GoInfo.Ticks, cHHStepTicks)
   350       inc(GoInfo.Ticks, cHHStepTicks)
   347       end;
   351       end;
   348    if not TestCollisionYwithGear(Gear, 1) then
   352    if not TestCollisionYwithGear(Gear, 1) then
   349    begin
   353    begin
   350    Gear.Y:= Gear.Y + 1;
   354    Gear^.Y:= Gear^.Y + 1;
   351    if not TestCollisionYwithGear(Gear, 1) then
   355    if not TestCollisionYwithGear(Gear, 1) then
   352    begin
   356    begin
   353    Gear.Y:= Gear.Y + 1;
   357    Gear^.Y:= Gear^.Y + 1;
   354    if not TestCollisionYwithGear(Gear, 1) then
   358    if not TestCollisionYwithGear(Gear, 1) then
   355    begin
   359    begin
   356    Gear.Y:= Gear.Y + 1;
   360    Gear^.Y:= Gear^.Y + 1;
   357    if not TestCollisionYwithGear(Gear, 1) then
   361    if not TestCollisionYwithGear(Gear, 1) then
   358    begin
   362    begin
   359    Gear.Y:= Gear.Y + 1;
   363    Gear^.Y:= Gear^.Y + 1;
   360    if not TestCollisionYwithGear(Gear, 1) then
   364    if not TestCollisionYwithGear(Gear, 1) then
   361    begin
   365    begin
   362    Gear.Y:= Gear.Y + 1;
   366    Gear^.Y:= Gear^.Y + 1;
   363    if not TestCollisionYwithGear(Gear, 1) then
   367    if not TestCollisionYwithGear(Gear, 1) then
   364    begin
   368    begin
   365    Gear.Y:= Gear.Y + 1;
   369    Gear^.Y:= Gear^.Y + 1;
   366    if not TestCollisionYwithGear(Gear, 1) then
   370    if not TestCollisionYwithGear(Gear, 1) then
   367       begin
   371       begin
   368       Gear.Y:= Gear.Y - 6;
   372       Gear^.Y:= Gear^.Y - 6;
   369       Gear.dY:= 0;
   373       Gear^.dY:= 0;
   370       Gear.dX:= 0.0000001 * hwSign(Gear.dX);
   374       Gear^.State:= Gear^.State or gstFalling
   371       Gear.State:= Gear.State or gstFalling
       
   372       end
   375       end
   373    end
   376    end
   374    end
   377    end
   375    end
   378    end
   376    end
   379    end
   377    end
   380    end
   378    end;
   381    end;
   379 if (pX <> round(Gear.X)) and ((Gear.State and gstFalling) = 0) then
   382 if (pX <> hwRound(Gear^.X)) and ((Gear^.State and gstFalling) = 0) then
   380    begin
   383    begin
   381    Result:= true;
   384    Result:= true;
   382    exit
   385    exit(Result)
   383    end
   386    end
   384 until (pX = round(Gear.X)) and (pY = round(Gear.Y)) and ((Gear.State and gstFalling) = 0);
   387 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstFalling) = 0);
   385 HHJump(AltGear, jmpHJump, GoInfo)
   388 HHJump(AltGear, jmpHJump, GoInfo)
   386 end;
   389 end;
   387 
   390 
   388 function rndSign(num: integer): integer;
   391 {function rndSign(num: integer): integer;
   389 begin
   392 begin
   390 if random(2) = 0 then Result:=   num
   393 if random(2) = 0 then Result:=   num
   391                  else Result:= - num
   394                  else Result:= - num
   392 end;  }
   395 end;  }
   393 
   396