hedgewars/uAIMisc.pas
changeset 2695 ed789a7ef68d
parent 2616 6e2b341dc408
child 2716 b9ca1bfca24f
equal deleted inserted replaced
2694:dcd248e04f3d 2695:ed789a7ef68d
   160 KnownExplosion.Radius:= r
   160 KnownExplosion.Radius:= r
   161 end;
   161 end;
   162 
   162 
   163 function RatePlace(Gear: PGear): LongInt;
   163 function RatePlace(Gear: PGear): LongInt;
   164 var i, r: LongInt;
   164 var i, r: LongInt;
   165     Result: LongInt;
   165     rate: LongInt;
   166 begin
   166 begin
   167 Result:= 0;
   167 rate:= 0;
   168 for i:= 0 to Pred(bonuses.Count) do
   168 for i:= 0 to Pred(bonuses.Count) do
   169 	with bonuses.ar[i] do
   169 	with bonuses.ar[i] do
   170 		begin
   170 		begin
   171 		r:= hwRound(Distance(Gear^.X - int2hwFloat(X), Gear^.Y - int2hwFloat(Y)));
   171 		r:= hwRound(Distance(Gear^.X - int2hwFloat(X), Gear^.Y - int2hwFloat(Y)));
   172 		if r < Radius then
   172 		if r < Radius then
   173 			inc(Result, Score * (Radius - r))
   173 			inc(rate, Score * (Radius - r))
   174 		end;
   174 		end;
   175 	RatePlace:= Result
   175 	RatePlace:= rate;
   176 end;
   176 end;
   177 
   177 
   178 // Wrapper to test various approaches.  If it works reasonably, will just replace.
   178 // Wrapper to test various approaches.  If it works reasonably, will just replace.
   179 // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with...
   179 // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with...
   180 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean;
   180 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean;
   202 if b then exit(true);
   202 if b then exit(true);
   203 TestColl:=(((x+r) and LAND_WIDTH_MASK) = 0)and(((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] <> 0)
   203 TestColl:=(((x+r) and LAND_WIDTH_MASK) = 0)and(((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] <> 0)
   204 end;
   204 end;
   205 
   205 
   206 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
   206 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
   207 var i, dmg, Result: LongInt;
   207 var i, dmg, rate: LongInt;
   208 begin
   208 begin
   209 Result:= 0;
   209 rate:= 0;
   210 // add our virtual position
   210 // add our virtual position
   211 with Targets.ar[Targets.Count] do
   211 with Targets.ar[Targets.Count] do
   212      begin
   212      begin
   213      Point.x:= hwRound(Me^.X);
   213      Point.x:= hwRound(Me^.X);
   214      Point.y:= hwRound(Me^.Y);
   214      Point.y:= hwRound(Me^.Y);
   221          dmg:= r + cHHRadius div 2 - hwRound(DistanceI(Point.x - x, Point.y - y));
   221          dmg:= r + cHHRadius div 2 - hwRound(DistanceI(Point.x - x, Point.y - y));
   222          if dmg > 0 then
   222          if dmg > 0 then
   223             begin
   223             begin
   224             dmg:= min(dmg div 2, r);
   224             dmg:= min(dmg div 2, r);
   225             if dmg >= abs(Score) then
   225             if dmg >= abs(Score) then
   226                if Score > 0 then inc(Result, KillScore)
   226                if Score > 0 then inc(rate, KillScore)
   227                             else dec(Result, KillScore * friendlyfactor div 100)
   227                             else dec(rate, KillScore * friendlyfactor div 100)
   228             else
   228             else
   229                if Score > 0 then inc(Result, dmg)
   229                if Score > 0 then inc(rate, dmg)
   230                             else dec(Result, dmg * friendlyfactor div 100)
   230                             else dec(rate, dmg * friendlyfactor div 100)
   231             end;
   231             end;
   232          end;
   232          end;
   233 RateExplosion:= Result * 1024
   233 RateExplosion:= rate * 1024;
   234 end;
   234 end;
   235 
   235 
   236 function RateShove(Me: PGear; x, y, r, power: LongInt): LongInt;
   236 function RateShove(Me: PGear; x, y, r, power: LongInt): LongInt;
   237 var i, dmg, Result: LongInt;
   237 var i, dmg, rate: LongInt;
   238 begin
   238 begin
   239 Result:= 0;
   239 rate:= 0;
   240 for i:= 0 to Pred(Targets.Count) do
   240 for i:= 0 to Pred(Targets.Count) do
   241     with Targets.ar[i] do
   241     with Targets.ar[i] do
   242          begin
   242          begin
   243          dmg:= r - hwRound(DistanceI(Point.x - x, Point.y - y));
   243          dmg:= r - hwRound(DistanceI(Point.x - x, Point.y - y));
   244          if dmg > 0 then
   244          if dmg > 0 then
   245             begin
   245             begin
   246             if power >= abs(Score) then
   246             if power >= abs(Score) then
   247                if Score > 0 then inc(Result, KillScore)
   247                if Score > 0 then inc(rate, KillScore)
   248                             else dec(Result, KillScore * friendlyfactor div 100)
   248                             else dec(rate, KillScore * friendlyfactor div 100)
   249             else
   249             else
   250                if Score > 0 then inc(Result, power)
   250                if Score > 0 then inc(rate, power)
   251                             else dec(Result, power * friendlyfactor div 100)
   251                             else dec(rate, power * friendlyfactor div 100)
   252             end;
   252             end;
   253          end;
   253          end;
   254 RateShove:= Result * 1024
   254 RateShove:= rate * 1024
   255 end;
   255 end;
   256 
   256 
   257 function RateShotgun(Me: PGear; x, y: LongInt): LongInt;
   257 function RateShotgun(Me: PGear; x, y: LongInt): LongInt;
   258 const
   258 const
   259   REUSE_BONUS = 1.35;
   259   REUSE_BONUS = 1.35;
   260 var i, dmg, Result: LongInt;
   260 var i, dmg, rate: LongInt;
   261 begin
   261 begin
   262 Result:= 0;
   262 rate:= 0;
   263 // add our virtual position
   263 // add our virtual position
   264 with Targets.ar[Targets.Count] do
   264 with Targets.ar[Targets.Count] do
   265      begin
   265      begin
   266      Point.x:= hwRound(Me^.X);
   266      Point.x:= hwRound(Me^.X);
   267      Point.y:= hwRound(Me^.Y);
   267      Point.y:= hwRound(Me^.Y);
   274          dmg:= min(cHHRadius + cShotgunRadius - hwRound(DistanceI(Point.x - x, Point.y - y)), 25);
   274          dmg:= min(cHHRadius + cShotgunRadius - hwRound(DistanceI(Point.x - x, Point.y - y)), 25);
   275          dmg := round(dmg * REUSE_BONUS);
   275          dmg := round(dmg * REUSE_BONUS);
   276          if dmg > 0 then
   276          if dmg > 0 then
   277             begin
   277             begin
   278                 if dmg >= abs(Score) then dmg := KillScore;
   278                 if dmg >= abs(Score) then dmg := KillScore;
   279                 if Score > 0 then inc(Result, dmg)
   279                 if Score > 0 then inc(rate, dmg)
   280                 else dec(Result, dmg * friendlyfactor div 100);
   280                 else dec(rate, dmg * friendlyfactor div 100);
   281             end;
   281             end;
   282          end;
   282          end;
   283 RateShotgun:= Result * 1024
   283 RateShotgun:= rate * 1024;
   284 end;
   284 end;
   285 
   285 
   286 function HHJump(Gear: PGear; JumpType: TJumpType; var GoInfo: TGoInfo): boolean;
   286 function HHJump(Gear: PGear; JumpType: TJumpType; var GoInfo: TGoInfo): boolean;
   287 var bX, bY: LongInt;
   287 var bX, bY: LongInt;
   288     Result: boolean;
   288     bRes: boolean;
   289 begin
   289 begin
   290 Result:= false;
   290 bRes:= false;
   291 GoInfo.Ticks:= 0;
   291 GoInfo.Ticks:= 0;
   292 GoInfo.FallPix:= 0;
   292 GoInfo.FallPix:= 0;
   293 GoInfo.JumpType:= jmpNone;
   293 GoInfo.JumpType:= jmpNone;
   294 bX:= hwRound(Gear^.X);
   294 bX:= hwRound(Gear^.X);
   295 bY:= hwRound(Gear^.Y);
   295 bY:= hwRound(Gear^.Y);
   296 case JumpType of
   296 case JumpType of
   297      jmpNone: exit(Result);
   297      jmpNone: exit(bRes);
   298     jmpHJump: if not TestCollisionYwithGear(Gear, -1) then
   298     jmpHJump: if not TestCollisionYwithGear(Gear, -1) then
   299                  begin
   299                  begin
   300                  Gear^.dY:= -_0_2;
   300                  Gear^.dY:= -_0_2;
   301                  SetLittle(Gear^.dX);
   301                  SetLittle(Gear^.dX);
   302                  Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
   302                  Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
   303                  end else exit(Result);
   303                  end else exit(bRes);
   304     jmpLJump: begin
   304     jmpLJump: begin
   305               if not TestCollisionYwithGear(Gear, -1) then
   305               if not TestCollisionYwithGear(Gear, -1) then
   306                  if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - int2hwFloat(2) else
   306                  if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - int2hwFloat(2) else
   307                  if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - _1;
   307                  if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - _1;
   308               if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
   308               if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
   309                  or   TestCollisionYwithGear(Gear, -1)) then
   309                  or   TestCollisionYwithGear(Gear, -1)) then
   310                  begin
   310                  begin
   311                  Gear^.dY:= -_0_15;
   311                  Gear^.dY:= -_0_15;
   312                  Gear^.dX:= SignAs(_0_15, Gear^.dX);
   312                  Gear^.dX:= SignAs(_0_15, Gear^.dX);
   313                  Gear^.State:= Gear^.State or gstMoving or gstHHJumping
   313                  Gear^.State:= Gear^.State or gstMoving or gstHHJumping
   314                  end else exit(Result)
   314                  end else exit(bRes)
   315               end
   315               end
   316     end;
   316     end;
   317 
   317 
   318 repeat
   318 repeat
   319 if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then exit(Result);
   319 if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then exit(bRes);
   320 if (Gear^.State and gstMoving) <> 0 then
   320 if (Gear^.State and gstMoving) <> 0 then
   321    begin
   321    begin
   322    if (GoInfo.Ticks = 350) then
   322    if (GoInfo.Ticks = 350) then
   323       if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
   323       if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
   324          begin
   324          begin
   327          end;
   327          end;
   328    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
   328    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
   329    Gear^.X:= Gear^.X + Gear^.dX;
   329    Gear^.X:= Gear^.X + Gear^.dX;
   330    inc(GoInfo.Ticks);
   330    inc(GoInfo.Ticks);
   331    Gear^.dY:= Gear^.dY + cGravity;
   331    Gear^.dY:= Gear^.dY + cGravity;
   332    if Gear^.dY > _0_4 then exit(Result);
   332    if Gear^.dY > _0_4 then exit(bRes);
   333    if (Gear^.dY.isNegative)and TestCollisionYwithGear(Gear, -1) then Gear^.dY:= _0;
   333    if (Gear^.dY.isNegative)and TestCollisionYwithGear(Gear, -1) then Gear^.dY:= _0;
   334    Gear^.Y:= Gear^.Y + Gear^.dY;
   334    Gear^.Y:= Gear^.Y + Gear^.dY;
   335    if (not Gear^.dY.isNegative)and TestCollisionYwithGear(Gear, 1) then
   335    if (not Gear^.dY.isNegative)and TestCollisionYwithGear(Gear, 1) then
   336       begin
   336       begin
   337       Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   337       Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   338       Gear^.dY:= _0;
   338       Gear^.dY:= _0;
   339       case JumpType of
   339       case JumpType of
   340            jmpHJump: if bY - hwRound(Gear^.Y) > 5 then
   340            jmpHJump: if bY - hwRound(Gear^.Y) > 5 then
   341                         begin
   341                         begin
   342                         Result:= true;
   342                         bRes:= true;
   343                         GoInfo.JumpType:= jmpHJump;
   343                         GoInfo.JumpType:= jmpHJump;
   344                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   344                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   345                         end;
   345                         end;
   346            jmpLJump: if abs(bX - hwRound(Gear^.X)) > 30 then
   346            jmpLJump: if abs(bX - hwRound(Gear^.X)) > 30 then
   347                         begin
   347                         begin
   348                         Result:= true;
   348                         bRes:= true;
   349                         GoInfo.JumpType:= jmpLJump;
   349                         GoInfo.JumpType:= jmpLJump;
   350                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   350                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   351                         end;
   351                         end;
   352            end;
   352            end;
   353       exit(Result)
   353       exit(bRes)
   354       end;
   354       end;
   355    end;
   355    end;
   356 until false
   356 until false
   357 end;
   357 end;
   358 
   358 
   359 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
   359 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
   360 var pX, pY: LongInt;
   360 var pX, pY: LongInt;
   361     Result: boolean;
   361     bRes: boolean;
   362 begin
   362 begin
   363 Result:= false;
   363 bRes:= false;
   364 AltGear^:= Gear^;
   364 AltGear^:= Gear^;
   365 
   365 
   366 GoInfo.Ticks:= 0;
   366 GoInfo.Ticks:= 0;
   367 GoInfo.FallPix:= 0;
   367 GoInfo.FallPix:= 0;
   368 GoInfo.JumpType:= jmpNone;
   368 GoInfo.JumpType:= jmpNone;
   376    Gear^.dY:= Gear^.dY + cGravity;
   376    Gear^.dY:= Gear^.dY + cGravity;
   377    if Gear^.dY > _0_4 then
   377    if Gear^.dY > _0_4 then
   378       begin
   378       begin
   379       Goinfo.FallPix:= 0;
   379       Goinfo.FallPix:= 0;
   380       HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall with damage
   380       HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall with damage
   381       exit(Result)
   381       exit(bRes)
   382       end;
   382       end;
   383    Gear^.Y:= Gear^.Y + Gear^.dY;
   383    Gear^.Y:= Gear^.Y + Gear^.dY;
   384    if hwRound(Gear^.Y) > pY then inc(GoInfo.FallPix);
   384    if hwRound(Gear^.Y) > pY then inc(GoInfo.FallPix);
   385    if TestCollisionYwithGear(Gear, 1) then
   385    if TestCollisionYwithGear(Gear, 1) then
   386       begin
   386       begin
   387       inc(GoInfo.Ticks, 410);
   387       inc(GoInfo.Ticks, 410);
   388       Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   388       Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   389       Gear^.dY:= _0;
   389       Gear^.dY:= _0;
   390       Result:= true;
   390       bRes:= true;
   391       HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall
   391       HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall
   392       exit(Result)
   392       exit(bRes)
   393       end;
   393       end;
   394    continue
   394    continue
   395    end;
   395    end;
   396    if (Gear^.Message and gm_Left  )<>0 then Gear^.dX:= -cLittle else
   396    if (Gear^.Message and gm_Left  )<>0 then Gear^.dX:= -cLittle else
   397    if (Gear^.Message and gm_Right )<>0 then Gear^.dX:=  cLittle else exit(Result);
   397    if (Gear^.Message and gm_Right )<>0 then Gear^.dX:=  cLittle else exit(bRes);
   398    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   398    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   399       begin
   399       begin
   400       if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
   400       if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
   401          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
   401          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
   402       if not (TestCollisionXwithXYShift(Gear, _0, -5, hwSign(Gear^.dX))
   402       if not (TestCollisionXwithXYShift(Gear, _0, -5, hwSign(Gear^.dX))
   448    end;
   448    end;
   449 if (pX <> hwRound(Gear^.X)) and ((Gear^.State and gstMoving) = 0) then
   449 if (pX <> hwRound(Gear^.X)) and ((Gear^.State and gstMoving) = 0) then
   450    exit(true);
   450    exit(true);
   451 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0);
   451 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0);
   452 HHJump(AltGear, jmpHJump, GoInfo);
   452 HHJump(AltGear, jmpHJump, GoInfo);
   453 HHGo:= Result
   453 HHGo:= bRes;
   454 end;
   454 end;
   455 
   455 
   456 function AIrndSign(num: LongInt): LongInt;
   456 function AIrndSign(num: LongInt): LongInt;
   457 begin
   457 begin
   458 if random(2) = 0 then AIrndSign:=   num
   458 if random(2) = 0 then AIrndSign:=   num