hedgewars/uAIMisc.pas
changeset 7041 76a9274f280f
parent 6990 40e5af28d026
child 7154 56e329edf4b8
equal deleted inserted replaced
7040:4aff2da0d0b3 7041:76a9274f280f
   214 // Wrapper to test various approaches.  If it works reasonably, will just replace.
   214 // Wrapper to test various approaches.  If it works reasonably, will just replace.
   215 // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with...
   215 // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with...
   216 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
   216 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
   217 var MeX, MeY: LongInt;
   217 var MeX, MeY: LongInt;
   218 begin
   218 begin
   219     TestCollExcludingMe:= false;
       
   220     if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then
   219     if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then
   221     begin
   220     begin
   222         MeX:= hwRound(Me^.X);
   221         MeX:= hwRound(Me^.X);
   223         MeY:= hwRound(Me^.Y);
   222         MeY:= hwRound(Me^.Y);
   224         // We are still inside the hog. Skip radius test
   223         // We are still inside the hog. Skip radius test
   225         if ((((x-MeX)*(x-MeX)) + ((y-MeY)*(y-MeY))) < 256) and ((Land[y, x] and $FF00) = 0) then
   224         if ((((x-MeX)*(x-MeX)) + ((y-MeY)*(y-MeY))) < 256) and ((Land[y, x] and $FF00) = 0) then
   226             exit;
   225             exit(false);
   227     end;
   226     end;
   228     TestCollExcludingMe:= TestColl(x, y, r)
   227     TestCollExcludingMe:= TestColl(x, y, r)
   229 end;
   228 end;
   230 
   229 
   231 function TestColl(x, y, r: LongInt): boolean; inline;
   230 function TestColl(x, y, r: LongInt): boolean; inline;
   232 var b: boolean;
   231 var b: boolean;
   233 begin
   232 begin
   234     TestColl:= true;
       
   235 
       
   236     b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] <> 0);
   233     b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] <> 0);
   237     if b then
   234     if b then
   238         exit;
   235         exit(true);
   239     
   236     
   240     b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] <> 0);
   237     b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] <> 0);
   241     if b then
   238     if b then
   242         exit;
   239         exit(true);
   243     
   240     
   244     b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] <> 0);
   241     b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] <> 0);
   245     if b then
   242     if b then
   246         exit;
   243         exit(true);
   247     
   244     
   248     b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] <> 0);
   245     b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] <> 0);
   249     if b then
   246     if b then
   250         exit;
   247         exit(true);
   251     
   248     
   252     TestColl:= false;
   249     TestColl:= false;
   253 end;
   250 end;
   254 
   251 
   255 function TestCollWithLand(x, y, r: LongInt): boolean; inline;
   252 function TestCollWithLand(x, y, r: LongInt): boolean; inline;
   256 var b: boolean;
   253 var b: boolean;
   257 begin
   254 begin
   258     TestCollWithLand:= true;
       
   259     
       
   260     b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] > 255);
   255     b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] > 255);
   261     if b then
   256     if b then
   262         exit;
   257         exit(true);
   263         
   258         
   264     b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] > 255);
   259     b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] > 255);
   265     if b then
   260     if b then
   266         exit;
   261         exit(true);
   267         
   262         
   268     b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] > 255);
   263     b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] > 255);
   269     if b then
   264     if b then
   270         exit;
   265         exit(true);
   271         
   266         
   272     b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] > 255);
   267     b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] > 255);
   273     if b then
   268     if b then
   274         exit;
   269         exit(true);
   275 
   270 
   276     TestCollWithLand:= false;
   271     TestCollWithLand:= false;
   277 end;
   272 end;
   278 
   273 
   279 function TraceFall(eX, eY: LongInt; x, y, dX, dY: Real; r: LongWord): LongInt;
   274 function TraceFall(eX, eY: LongInt; x, y, dX, dY: Real; r: LongWord): LongInt;
   296         begin
   291         begin
   297             if 0.4 < dY then
   292             if 0.4 < dY then
   298             begin
   293             begin
   299                 dmg := 1 + trunc((abs(dY) - 0.4) * 70);
   294                 dmg := 1 + trunc((abs(dY) - 0.4) * 70);
   300                 if dmg >= 1 then
   295                 if dmg >= 1 then
   301                 begin
   296                     exit(dmg);
   302                     TraceFall:= dmg;
   297             end;
   303                     exit
   298             exit(0)
   304                 end;
       
   305             end;
       
   306             TraceFall:= 0;
       
   307             exit
       
   308         end;
   299         end;
   309         if (y > cWaterLine) or (x > 4096) or (x < 0) then
   300         if (y > cWaterLine) or (x > 4096) or (x < 0) then
   310         begin
   301             exit(-1);
   311             // returning -1 for drowning so it can be considered in the Rate routine
       
   312             TraceFall:= -1;
       
   313             exit;
       
   314         end;
       
   315     end;
   302     end;
   316 end;
   303 end;
   317 
   304 
   318 function TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt;
   305 function TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt;
   319 var dmg: LongInt;
   306 var dmg: LongInt;
   328         begin
   315         begin
   329             if 0.4 < dY then
   316             if 0.4 < dY then
   330             begin
   317             begin
   331                 dmg := 1 + trunc((abs(dY) - 0.4) * 70);
   318                 dmg := 1 + trunc((abs(dY) - 0.4) * 70);
   332                 if dmg >= 1 then
   319                 if dmg >= 1 then
   333                 begin
   320                     exit(dmg);
   334                     TraceShoveFall:= dmg;
   321             end;
   335                     exit
   322             exit(0)
   336                 end;
       
   337             end;
       
   338             TraceShoveFall:= 0;
       
   339             exit
       
   340         end;
   323         end;
   341         if (y > cWaterLine) or (x > 4096) or (x < 0) then
   324         if (y > cWaterLine) or (x > 4096) or (x < 0) then
   342         begin
       
   343             // returning -1 for drowning so it can be considered in the Rate routine
   325             // returning -1 for drowning so it can be considered in the Rate routine
   344             TraceShoveFall:= -1;
   326             exit(-1)
   345             exit;
       
   346         end;
       
   347     end;
   327     end;
   348 end;
   328 end;
   349 
   329 
   350 // Flags are not defined yet but 1 for checking drowning and 2 for assuming land erasure.
   330 // Flags are not defined yet but 1 for checking drowning and 2 for assuming land erasure.
   351 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
   331 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
   533 GoInfo.Ticks:= 0;
   513 GoInfo.Ticks:= 0;
   534 GoInfo.JumpType:= jmpNone;
   514 GoInfo.JumpType:= jmpNone;
   535 bX:= hwRound(Gear^.X);
   515 bX:= hwRound(Gear^.X);
   536 bY:= hwRound(Gear^.Y);
   516 bY:= hwRound(Gear^.Y);
   537 case JumpType of
   517 case JumpType of
   538     jmpNone: exit;
   518     jmpNone: exit(false);
   539     
   519     
   540     jmpHJump:
   520     jmpHJump:
   541         if TestCollisionYwithGear(Gear, -1) = 0 then
   521         if TestCollisionYwithGear(Gear, -1) = 0 then
   542         begin
   522         begin
   543             Gear^.dY:= -_0_2;
   523             Gear^.dY:= -_0_2;
   544             SetLittle(Gear^.dX);
   524             SetLittle(Gear^.dX);
   545             Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
   525             Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
   546         end
   526         end
   547     else
   527     else
   548         exit;
   528         exit(false);
   549         
   529         
   550     jmpLJump:
   530     jmpLJump:
   551         begin
   531         begin
   552             if TestCollisionYwithGear(Gear, -1) <> 0 then
   532             if TestCollisionYwithGear(Gear, -1) <> 0 then
   553                 if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
   533                 if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
   561                 Gear^.dY:= -_0_15;
   541                 Gear^.dY:= -_0_15;
   562                 Gear^.dX:= SignAs(_0_15, Gear^.dX);
   542                 Gear^.dX:= SignAs(_0_15, Gear^.dX);
   563                 Gear^.State:= Gear^.State or gstMoving or gstHHJumping
   543                 Gear^.State:= Gear^.State or gstMoving or gstHHJumping
   564             end
   544             end
   565         else
   545         else
   566             exit
   546             exit(false)
   567         end
   547         end
   568 end;
   548 end;
   569 
   549 
   570 repeat
   550 repeat
   571     if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then
   551     if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then
   572         exit;
   552         exit(false);
   573     if (Gear^.State and gstMoving) <> 0 then
   553     if (Gear^.State and gstMoving) <> 0 then
   574     begin
   554     begin
   575         if (GoInfo.Ticks = 350) then
   555         if (GoInfo.Ticks = 350) then
   576             if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
   556             if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
   577             begin
   557             begin
   581         if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
   561         if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
   582             Gear^.X:= Gear^.X + Gear^.dX;
   562             Gear^.X:= Gear^.X + Gear^.dX;
   583         inc(GoInfo.Ticks);
   563         inc(GoInfo.Ticks);
   584         Gear^.dY:= Gear^.dY + cGravity;
   564         Gear^.dY:= Gear^.dY + cGravity;
   585         if Gear^.dY > _0_4 then
   565         if Gear^.dY > _0_4 then
   586             exit;
   566             exit(false);
   587         if (Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, -1) <> 0) then
   567         if (Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, -1) <> 0) then
   588             Gear^.dY:= _0;
   568             Gear^.dY:= _0;
   589         Gear^.Y:= Gear^.Y + Gear^.dY;
   569         Gear^.Y:= Gear^.Y + Gear^.dY;
   590         if (not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) <> 0) then
   570         if (not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) <> 0) then
   591         begin
   571             begin
   592             Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   572             Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   593             Gear^.dY:= _0;
   573             Gear^.dY:= _0;
   594             case JumpType of
   574             case JumpType of
   595                 jmpHJump:
   575                 jmpHJump:
   596                     if bY - hwRound(Gear^.Y) > 5 then
   576                     if bY - hwRound(Gear^.Y) > 5 then
   597                     begin
   577                         begin
   598                         HHJump:= true;
       
   599                         GoInfo.JumpType:= jmpHJump;
   578                         GoInfo.JumpType:= jmpHJump;
   600                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   579                         inc(GoInfo.Ticks, 300 + 300); // 300 before jump, 300 after
   601                     end;
   580                         exit(true)
       
   581                         end;
   602                 jmpLJump:
   582                 jmpLJump:
   603                     if abs(bX - hwRound(Gear^.X)) > 30 then
   583                     if abs(bX - hwRound(Gear^.X)) > 30 then
   604                     begin
   584                         begin
   605                         HHJump:= true;
       
   606                         GoInfo.JumpType:= jmpLJump;
   585                         GoInfo.JumpType:= jmpLJump;
   607                         inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
   586                         inc(GoInfo.Ticks, 300 + 300); // 300 before jump, 300 after
   608                     end
   587                         exit(true)
   609             end;
   588                         end
   610             exit
   589                 end;
   611         end;
   590             exit(false)
       
   591             end;
   612     end;
   592     end;
   613 until false
   593 until false
   614 end;
   594 end;
   615 
   595 
   616 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
   596 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
   624 GoInfo.JumpType:= jmpNone;
   604 GoInfo.JumpType:= jmpNone;
   625 repeat
   605 repeat
   626 pX:= hwRound(Gear^.X);
   606 pX:= hwRound(Gear^.X);
   627 pY:= hwRound(Gear^.Y);
   607 pY:= hwRound(Gear^.Y);
   628 if pY + cHHRadius >= cWaterLine then
   608 if pY + cHHRadius >= cWaterLine then
   629     exit;
   609     exit(false);
   630 if (Gear^.State and gstMoving) <> 0 then
   610 if (Gear^.State and gstMoving) <> 0 then
   631     begin
   611     begin
   632     inc(GoInfo.Ticks);
   612     inc(GoInfo.Ticks);
   633     Gear^.dY:= Gear^.dY + cGravity;
   613     Gear^.dY:= Gear^.dY + cGravity;
   634     if Gear^.dY > _0_4 then
   614     if Gear^.dY > _0_4 then
   635         begin
   615         begin
   636         Goinfo.FallPix:= 0;
   616         Goinfo.FallPix:= 0;
   637         HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall with damage
   617         HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall with damage
   638         exit
   618         exit(false)
   639         end;
   619         end;
   640     Gear^.Y:= Gear^.Y + Gear^.dY;
   620     Gear^.Y:= Gear^.Y + Gear^.dY;
   641     if hwRound(Gear^.Y) > pY then
   621     if hwRound(Gear^.Y) > pY then
   642         inc(GoInfo.FallPix);
   622         inc(GoInfo.FallPix);
   643     if TestCollisionYwithGear(Gear, 1) <> 0 then
   623     if TestCollisionYwithGear(Gear, 1) <> 0 then
   645         inc(GoInfo.Ticks, 410);
   625         inc(GoInfo.Ticks, 410);
   646         Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   626         Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
   647         Gear^.dY:= _0;
   627         Gear^.dY:= _0;
   648         HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall
   628         HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall
   649         HHGo:= true;
   629         HHGo:= true;
   650         exit
   630         exit(false)
   651         end;
   631         end;
   652     continue
   632     continue
   653     end;
   633     end;
   654     if (Gear^.Message and gmLeft  )<>0 then
   634     if (Gear^.Message and gmLeft  )<>0 then
   655         Gear^.dX:= -cLittle
   635         Gear^.dX:= -cLittle
   656     else
   636     else
   657         if (Gear^.Message and gmRight )<>0 then
   637         if (Gear^.Message and gmRight )<>0 then
   658             Gear^.dX:=  cLittle
   638             Gear^.dX:=  cLittle
   659         else
   639         else
   660             exit;
   640             exit(false);
   661     if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   641     if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   662         begin
   642         begin
   663         if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
   643         if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
   664         or (TestCollisionYwithGear(Gear, -1) <> 0)) then
   644         or (TestCollisionYwithGear(Gear, -1) <> 0)) then
   665             Gear^.Y:= Gear^.Y - _1;
   645             Gear^.Y:= Gear^.Y - _1;
   726     end
   706     end
   727     end
   707     end
   728     end
   708     end
   729     end;
   709     end;
   730 if (pX <> hwRound(Gear^.X)) and ((Gear^.State and gstMoving) = 0) then
   710 if (pX <> hwRound(Gear^.X)) and ((Gear^.State and gstMoving) = 0) then
   731 begin
   711     exit(true)
   732     HHGo:= true;
       
   733     exit;
       
   734 end;
       
   735 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0);
   712 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0);
   736 HHJump(AltGear, jmpHJump, GoInfo);
   713 HHJump(AltGear, jmpHJump, GoInfo);
   737 end;
   714 end;
   738 
   715 
   739 function AIrndSign(num: LongInt): LongInt;
   716 function AIrndSign(num: LongInt): LongInt;