hedgewars/uAIAmmoTests.pas
changeset 6474 42e9773eedfd
parent 6453 11c578d30bd3
child 6580 6155187bf599
equal deleted inserted replaced
6473:2bed5ba1a7ea 6474:42e9773eedfd
   122 end;
   122 end;
   123 
   123 
   124 function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   124 function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   125 var Vx, Vy, r, mX, mY: real;
   125 var Vx, Vy, r, mX, mY: real;
   126     rTime: LongInt;
   126     rTime: LongInt;
   127     Score, EX, EY: LongInt;
   127     EX, EY: LongInt;
   128     valueResult: LongInt;
   128     valueResult: LongInt;
   129 
   129     x, y, dX, dY: real;
   130     function CheckTrace: LongInt;
   130     t: LongInt;
   131     var x, y, dX, dY: real;
   131     value: LongInt;
   132         t: LongInt;
       
   133         value: LongInt;
       
   134     begin
       
   135     x:= mX;
       
   136     y:= mY;
       
   137     dX:= Vx;
       
   138     dY:= -Vy;
       
   139     t:= rTime;
       
   140     repeat
       
   141       x:= x + dX;
       
   142       y:= y + dY;
       
   143       dX:= dX + cWindSpeedf;
       
   144       dY:= dY + cGravityf;
       
   145       dec(t)
       
   146     until TestCollExcludingMe(Me, trunc(x), trunc(y), 5) or (t <= 0);
       
   147     EX:= trunc(x);
       
   148     EY:= trunc(y);
       
   149     value:= RateExplosion(Me, EX, EY, 101);
       
   150     if value = 0 then value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
       
   151     CheckTrace:= value;
       
   152     end;
       
   153 
       
   154 begin
   132 begin
   155 mX:= hwFloat2Float(Me^.X);
   133 mX:= hwFloat2Float(Me^.X);
   156 mY:= hwFloat2Float(Me^.Y);
   134 mY:= hwFloat2Float(Me^.Y);
   157 ap.Time:= 0;
   135 ap.Time:= 0;
   158 rTime:= 350;
   136 rTime:= 350;
   163   Vx:= - cWindSpeedf * rTime * 0.5 + (Targ.X + AIrndSign(2) - mX) / rTime;
   141   Vx:= - cWindSpeedf * rTime * 0.5 + (Targ.X + AIrndSign(2) - mX) / rTime;
   164   Vy:= cGravityf * rTime * 0.5 - (Targ.Y - mY) / rTime;
   142   Vy:= cGravityf * rTime * 0.5 - (Targ.Y - mY) / rTime;
   165   r:= sqrt(sqr(Vx) + sqr(Vy));
   143   r:= sqrt(sqr(Vx) + sqr(Vy));
   166   if not (r > 1) then
   144   if not (r > 1) then
   167      begin
   145      begin
   168      Score:= CheckTrace;
   146         x:= mX;
   169      if valueResult <= Score then
   147         y:= mY;
       
   148         dX:= Vx;
       
   149         dY:= -Vy;
       
   150         t:= rTime;
       
   151         repeat
       
   152               x:= x + dX;
       
   153               y:= y + dY;
       
   154               dX:= dX + cWindSpeedf;
       
   155               dY:= dY + cGravityf;
       
   156               dec(t)
       
   157         until TestCollExcludingMe(Me, trunc(x), trunc(y), 5) or (t <= 0);
       
   158         EX:= trunc(x);
       
   159         EY:= trunc(y);
       
   160         value:= RateExplosion(Me, EX, EY, 101);
       
   161         if value = 0 then value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
       
   162      if valueResult <= value then
   170         begin
   163         begin
   171         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
   164         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
   172         ap.Power:= trunc(r * cMaxPower) - random((Level - 1) * 17 + 1);
   165         ap.Power:= trunc(r * cMaxPower) - random((Level - 1) * 17 + 1);
   173         ap.ExplR:= 100;
   166         ap.ExplR:= 100;
   174         ap.ExplX:= EX;
   167         ap.ExplX:= EX;
   175         ap.ExplY:= EY;
   168         ap.ExplY:= EY;
   176         valueResult:= Score
   169         valueResult:= value
   177         end;
   170         end;
   178      end
   171      end
   179 until (rTime > 4250);
   172 until (rTime > 4250);
   180 TestBazooka:= valueResult
   173 TestBazooka:= valueResult
   181 end;
   174 end;
   182 
   175 
   183 function TestSnowball(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   176 function TestSnowball(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   184 var Vx, Vy, r: hwFloat;
   177 var Vx, Vy, r: hwFloat;
   185     rTime: LongInt;
   178     rTime: LongInt;
   186     Score, EX, EY: LongInt;
   179     EX, EY: LongInt;
   187     valueResult: LongInt;
   180     valueResult: LongInt;
   188 
   181     x, y, dX, dY: hwFloat;
   189     function CheckTrace: LongInt;
   182     t: LongInt;
   190     var x, y, dX, dY: hwFloat;
   183     value: LongInt;
   191         t: LongInt;
       
   192         value: LongInt;
       
   193     begin
       
   194     x:= Me^.X;
       
   195     y:= Me^.Y;
       
   196     dX:= Vx;
       
   197     dY:= -Vy;
       
   198     t:= rTime;
       
   199     repeat
       
   200       x:= x + dX;
       
   201       y:= y + dY;
       
   202       dX:= dX + cWindSpeed;
       
   203       dY:= dY + cGravity;
       
   204       dec(t)
       
   205     until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t <= 0);
       
   206     EX:= hwRound(x);
       
   207     EY:= hwRound(y);
       
   208     value:= RateExplosion(Me, EX, EY, 5);
       
   209     if value = 0 then value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
       
   210     CheckTrace:= value;
       
   211     end;
       
   212 
   184 
   213 begin
   185 begin
   214 ap.Time:= 0;
   186 ap.Time:= 0;
   215 rTime:= 350;
   187 rTime:= 350;
   216 ap.ExplR:= 0;
   188 ap.ExplR:= 0;
   220   Vx:= - cWindSpeed * rTime * _0_5 + (int2hwFloat(Targ.X + AIrndSign(2)) - Me^.X) / int2hwFloat(rTime);
   192   Vx:= - cWindSpeed * rTime * _0_5 + (int2hwFloat(Targ.X + AIrndSign(2)) - Me^.X) / int2hwFloat(rTime);
   221   Vy:= cGravity * rTime * _0_5 - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(rTime);
   193   Vy:= cGravity * rTime * _0_5 - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(rTime);
   222   r:= Distance(Vx, Vy);
   194   r:= Distance(Vx, Vy);
   223   if not (r > _1) then
   195   if not (r > _1) then
   224      begin
   196      begin
   225      Score:= CheckTrace;
   197         x:= Me^.X;
   226      if valueResult <= Score then
   198         y:= Me^.Y;
   227         begin
   199         dX:= Vx;
   228         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
   200         dY:= -Vy;
   229         ap.Power:= hwRound(r * cMaxPower) - random((Level - 1) * 17 + 1);
   201         t:= rTime;
   230         ap.ExplR:= 100;
   202         repeat
   231         ap.ExplX:= EX;
   203           x:= x + dX;
   232         ap.ExplY:= EY;
   204           y:= y + dY;
   233         valueResult:= Score
   205           dX:= dX + cWindSpeed;
   234         end;
   206           dY:= dY + cGravity;
       
   207           dec(t)
       
   208         until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t <= 0);
       
   209         EX:= hwRound(x);
       
   210         EY:= hwRound(y);
       
   211         value:= RateExplosion(Me, EX, EY, 5);
       
   212         if value = 0 then value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
       
   213 
       
   214         if valueResult <= value then
       
   215             begin
       
   216             ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
       
   217             ap.Power:= hwRound(r * cMaxPower) - random((Level - 1) * 17 + 1);
       
   218             ap.ExplR:= 100;
       
   219             ap.ExplX:= EX;
       
   220             ap.ExplY:= EY;
       
   221             valueResult:= value
       
   222             end;
   235      end
   223      end
   236 until (rTime > 4250);
   224 until (rTime > 4250);
   237 TestSnowball:= valueResult
   225 TestSnowball:= valueResult
   238 end;
   226 end;
   239 
   227 
   240 function TestMolotov(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   228 function TestMolotov(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   241 var Vx, Vy, r: hwFloat;
   229 var Vx, Vy, r: hwFloat;
   242     Score, EX, EY, valueResult: LongInt;
   230     Score, EX, EY, valueResult: LongInt;
   243     TestTime: Longword;
   231     TestTime: Longword;
   244 
   232     x, y, dY: hwFloat;
   245     function CheckTrace: LongInt;
   233     t: LongInt;
   246     var x, y, dY: hwFloat;
   234 begin
   247         t: LongInt;
   235 valueResult:= BadTurn;
       
   236 TestTime:= 0;
       
   237 ap.ExplR:= 0;
       
   238 repeat
       
   239   inc(TestTime, 300);
       
   240   Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime);
       
   241   Vy:= cGravity * (TestTime div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime);
       
   242   r:= Distance(Vx, Vy);
       
   243   if not (r > _1) then
       
   244      begin
       
   245         x:= Me^.X;
       
   246         y:= Me^.Y;
       
   247         dY:= -Vy;
       
   248         t:= TestTime;
       
   249         repeat
       
   250           x:= x + Vx;
       
   251           y:= y + dY;
       
   252           dY:= dY + cGravity;
       
   253           dec(t)
       
   254         until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 7) or (t = 0);
       
   255         EX:= hwRound(x);
       
   256         EY:= hwRound(y);
       
   257         if t < 50 then Score:= RateExplosion(Me, EX, EY, 97)  // average of 17 attempts, most good, but some failing spectacularly
       
   258                   else Score:= BadTurn;
       
   259                   
       
   260         if valueResult < Score then
       
   261             begin
       
   262             ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
       
   263             ap.Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 15);
       
   264             ap.Time:= TestTime;
       
   265             ap.ExplR:= 100;
       
   266             ap.ExplX:= EX;
       
   267             ap.ExplY:= EY;
       
   268             valueResult:= Score
       
   269             end;
       
   270      end
       
   271 until (TestTime > 4250);
       
   272 TestMolotov:= valueResult
       
   273 end;
       
   274 
       
   275 function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
       
   276 const tDelta = 24;
       
   277 var Vx, Vy, r: hwFloat;
       
   278     Score, EX, EY, valueResult: LongInt;
       
   279     TestTime: Longword;
       
   280     x, y, dY: hwFloat;
       
   281     t: LongInt;
       
   282 begin
       
   283 valueResult:= BadTurn;
       
   284 TestTime:= 0;
       
   285 ap.ExplR:= 0;
       
   286 repeat
       
   287   inc(TestTime, 1000);
       
   288   Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta);
       
   289   Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime + tDelta);
       
   290   r:= Distance(Vx, Vy);
       
   291   if not (r > _1) then
   248     begin
   292     begin
   249     x:= Me^.X;
   293     x:= Me^.X;
   250     y:= Me^.Y;
   294     y:= Me^.Y;
   251     dY:= -Vy;
   295     dY:= -Vy;
   252     t:= TestTime;
   296     t:= TestTime;
   253     repeat
   297     repeat
   254       x:= x + Vx;
   298         x:= x + Vx;
   255       y:= y + dY;
   299         y:= y + dY;
   256       dY:= dY + cGravity;
   300         dY:= dY + cGravity;
   257       dec(t)
   301         dec(t)
   258     until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 7) or (t = 0);
   302     until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t = 0);
   259     EX:= hwRound(x);
   303     EX:= hwRound(x);
   260     EY:= hwRound(y);
   304     EY:= hwRound(y);
   261     if t < 50 then CheckTrace:= RateExplosion(Me, EX, EY, 97)  // average of 17 attempts, most good, but some failing spectacularly
   305     if t < 50 then 
   262               else CheckTrace:= BadTurn
   306         Score:= RateExplosion(Me, EX, EY, 101)
   263     end;
   307     else 
   264 begin
   308         Score:= BadTurn;
   265 valueResult:= BadTurn;
   309 
   266 TestTime:= 0;
   310     if valueResult < Score then
   267 ap.ExplR:= 0;
       
   268 repeat
       
   269   inc(TestTime, 300);
       
   270   Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime);
       
   271   Vy:= cGravity * (TestTime div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime);
       
   272   r:= Distance(Vx, Vy);
       
   273   if not (r > _1) then
       
   274      begin
       
   275      Score:= CheckTrace;
       
   276      if valueResult < Score then
       
   277         begin
   311         begin
   278         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
   312         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
   279         ap.Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 15);
   313         ap.Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 15);
   280         ap.Time:= TestTime;
   314         ap.Time:= TestTime;
   281         ap.ExplR:= 100;
   315         ap.ExplR:= 100;
   282         ap.ExplX:= EX;
   316         ap.ExplX:= EX;
   283         ap.ExplY:= EY;
   317         ap.ExplY:= EY;
   284         valueResult:= Score
   318         valueResult:= Score
   285         end;
   319         end;
   286      end
   320     end
   287 until (TestTime > 4250);
       
   288 TestMolotov:= valueResult
       
   289 end;
       
   290 
       
   291 function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
       
   292 const tDelta = 24;
       
   293 var Vx, Vy, r: hwFloat;
       
   294     Score, EX, EY, valueResult: LongInt;
       
   295     TestTime: Longword;
       
   296 
       
   297     function CheckTrace: LongInt;
       
   298     var x, y, dY: hwFloat;
       
   299         t: LongInt;
       
   300     begin
       
   301     x:= Me^.X;
       
   302     y:= Me^.Y;
       
   303     dY:= -Vy;
       
   304     t:= TestTime;
       
   305     repeat
       
   306       x:= x + Vx;
       
   307       y:= y + dY;
       
   308       dY:= dY + cGravity;
       
   309       dec(t)
       
   310     until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t = 0);
       
   311     EX:= hwRound(x);
       
   312     EY:= hwRound(y);
       
   313     if t < 50 then CheckTrace:= RateExplosion(Me, EX, EY, 101)
       
   314               else CheckTrace:= BadTurn
       
   315     end;
       
   316 begin
       
   317 valueResult:= BadTurn;
       
   318 TestTime:= 0;
       
   319 ap.ExplR:= 0;
       
   320 repeat
       
   321   inc(TestTime, 1000);
       
   322   Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta);
       
   323   Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime + tDelta);
       
   324   r:= Distance(Vx, Vy);
       
   325   if not (r > _1) then
       
   326      begin
       
   327      Score:= CheckTrace;
       
   328      if valueResult < Score then
       
   329         begin
       
   330         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
       
   331         ap.Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 15);
       
   332         ap.Time:= TestTime;
       
   333         ap.ExplR:= 100;
       
   334         ap.ExplX:= EX;
       
   335         ap.ExplY:= EY;
       
   336         valueResult:= Score
       
   337         end;
       
   338      end
       
   339 until (TestTime = 4000);
   321 until (TestTime = 4000);
   340 TestGrenade:= valueResult
   322 TestGrenade:= valueResult
   341 end;
   323 end;
   342 
   324 
   343 function TestClusterBomb(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   325 function TestClusterBomb(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   344 const tDelta = 24;
   326 const tDelta = 24;
   345 var Vx, Vy, r: hwFloat;
   327 var Vx, Vy, r: hwFloat;
   346     Score, EX, EY, valueResult: LongInt;
   328     Score, EX, EY, valueResult: LongInt;
   347     TestTime: Longword;
   329     TestTime: Longword;
   348 
   330     x, y, dY: hwFloat;
   349     function CheckTrace: LongInt;
   331     t: LongInt;
   350     var x, y, dY: hwFloat;
       
   351         t: LongInt;
       
   352     begin
       
   353     x:= Me^.X;
       
   354     y:= Me^.Y;
       
   355     dY:= -Vy;
       
   356     t:= TestTime;
       
   357     repeat
       
   358       x:= x + Vx;
       
   359       y:= y + dY;
       
   360       dY:= dY + cGravity;
       
   361       dec(t)
       
   362     until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t = 0);
       
   363     EX:= hwRound(x);
       
   364     EY:= hwRound(y);
       
   365     if t < 50 then CheckTrace:= RateExplosion(Me, EX, EY, 41)
       
   366               else CheckTrace:= BadTurn
       
   367     end;
       
   368 begin
   332 begin
   369 valueResult:= BadTurn;
   333 valueResult:= BadTurn;
   370 TestTime:= 0;
   334 TestTime:= 0;
   371 ap.ExplR:= 0;
   335 ap.ExplR:= 0;
   372 repeat
   336 repeat
   378       Vx:= (int2hwFloat(Targ.X-10) - Me^.X) / int2hwFloat(TestTime + tDelta);
   342       Vx:= (int2hwFloat(Targ.X-10) - Me^.X) / int2hwFloat(TestTime + tDelta);
   379   Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y-150) - Me^.Y) / int2hwFloat(TestTime + tDelta);
   343   Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y-150) - Me^.Y) / int2hwFloat(TestTime + tDelta);
   380   r:= Distance(Vx, Vy);
   344   r:= Distance(Vx, Vy);
   381   if not (r > _1) then
   345   if not (r > _1) then
   382      begin
   346      begin
   383      Score:= CheckTrace;
   347     x:= Me^.X;
       
   348     y:= Me^.Y;
       
   349     dY:= -Vy;
       
   350     t:= TestTime;
       
   351     repeat
       
   352         x:= x + Vx;
       
   353         y:= y + dY;
       
   354         dY:= dY + cGravity;
       
   355         dec(t)
       
   356     until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t = 0);
       
   357     EX:= hwRound(x);
       
   358     EY:= hwRound(y);
       
   359     if t < 50 then 
       
   360         Score:= RateExplosion(Me, EX, EY, 41)
       
   361     else 
       
   362         Score:= BadTurn;
       
   363 
   384      if valueResult < Score then
   364      if valueResult < Score then
   385         begin
   365         begin
   386         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
   366         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
   387         ap.Power:= hwRound(r * cMaxPower * _0_9) + AIrndSign(random(Level) * 15);
   367         ap.Power:= hwRound(r * cMaxPower * _0_9) + AIrndSign(random(Level) * 15);
   388         ap.Time:= TestTime;
   368         ap.Time:= TestTime;
   399 function TestWatermelon(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   379 function TestWatermelon(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   400 const tDelta = 24;
   380 const tDelta = 24;
   401 var Vx, Vy, r: hwFloat;
   381 var Vx, Vy, r: hwFloat;
   402     Score, EX, EY, valueResult: LongInt;
   382     Score, EX, EY, valueResult: LongInt;
   403     TestTime: Longword;
   383     TestTime: Longword;
   404 
   384     x, y, dY: hwFloat;
   405     function CheckTrace: LongInt;
   385     t: LongInt;
   406     var x, y, dY: hwFloat;
   386 begin
   407         t: LongInt;
   387 valueResult:= BadTurn;
       
   388 TestTime:= 0;
       
   389 ap.ExplR:= 0;
       
   390 repeat
       
   391   inc(TestTime, 1000);
       
   392   Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta);
       
   393   Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y-200) - Me^.Y) / int2hwFloat(TestTime + tDelta);
       
   394   r:= Distance(Vx, Vy);
       
   395   if not (r > _1) then
   408     begin
   396     begin
   409     x:= Me^.X;
   397     x:= Me^.X;
   410     y:= Me^.Y;
   398     y:= Me^.Y;
   411     dY:= -Vy;
   399     dY:= -Vy;
   412     t:= TestTime;
   400     t:= TestTime;
   413     repeat
   401     repeat
   414       x:= x + Vx;
   402         x:= x + Vx;
   415       y:= y + dY;
   403         y:= y + dY;
   416       dY:= dY + cGravity;
   404         dY:= dY + cGravity;
   417       dec(t)
   405         dec(t)
   418     until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t = 0);
   406     until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t = 0);
   419     EX:= hwRound(x);
   407     EX:= hwRound(x);
   420     EY:= hwRound(y);
   408     EY:= hwRound(y);
   421     if t < 50 then CheckTrace:= RateExplosion(Me, EX, EY, 381)
   409     if t < 50 then 
   422               else CheckTrace:= BadTurn
   410         Score:= RateExplosion(Me, EX, EY, 381)
   423     end;
   411     else 
   424 begin
   412         Score:= BadTurn;
   425 valueResult:= BadTurn;
   413         
   426 TestTime:= 0;
   414     if valueResult < Score then
   427 ap.ExplR:= 0;
       
   428 repeat
       
   429   inc(TestTime, 1000);
       
   430   Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta);
       
   431   Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y-200) - Me^.Y) / int2hwFloat(TestTime + tDelta);
       
   432   r:= Distance(Vx, Vy);
       
   433   if not (r > _1) then
       
   434      begin
       
   435      Score:= CheckTrace;
       
   436      if valueResult < Score then
       
   437         begin
   415         begin
   438         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
   416         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
   439         ap.Power:= hwRound(r * cMaxPower * _0_9) + AIrndSign(random(Level) * 15);
   417         ap.Power:= hwRound(r * cMaxPower * _0_9) + AIrndSign(random(Level) * 15);
   440         ap.Time:= TestTime;
   418         ap.Time:= TestTime;
   441         ap.ExplR:= 300;
   419         ap.ExplR:= 300;
   442         ap.ExplX:= EX;
   420         ap.ExplX:= EX;
   443         ap.ExplY:= EY;
   421         ap.ExplY:= EY;
   444         valueResult:= Score
   422         valueResult:= Score
   445         end;
   423         end;
   446      end
   424     end
   447 until (TestTime = 4000);
   425 until (TestTime = 4000);
   448 TestWatermelon:= valueResult
   426 TestWatermelon:= valueResult
   449 end;
   427 end;
   450 
   428 
   451 function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   429 
   452 //const tDelta = 24;
   430     function Solve(TX, TY, MX, MY: LongInt): LongWord;
   453 var Vx, Vy: hwFloat;
       
   454     Score, EX, EY, valueResult: LongInt;
       
   455     TestTime: Longword;
       
   456 
       
   457     function CheckTrace: LongInt;
       
   458     var x, y, dY: hwFloat;
       
   459         value: LongInt;
       
   460     begin
       
   461         x:= Me^.X;
       
   462         y:= Me^.Y;
       
   463         dY:= -Vy;
       
   464 
       
   465         repeat
       
   466             x:= x + Vx;
       
   467             y:= y + dY;
       
   468             dY:= dY + cGravity;
       
   469             EX:= hwRound(x);
       
   470             EY:= hwRound(y);
       
   471         until TestCollExcludingMe(Me, EX, EY, 5) or (EY > cWaterLine);
       
   472 
       
   473         if (EY < cWaterLine) and (not dY.isNegative) then
       
   474             begin
       
   475             value:= RateExplosion(Me, EX, EY, 91);
       
   476             if (value = 0) then
       
   477                 if (dY > _0_15) then
       
   478                     value:= - abs(Targ.Y - EY) div 32
       
   479                 else
       
   480                     value:= BadTurn
       
   481             else if (value < 0) then value:= BadTurn
       
   482             end
       
   483         else
       
   484             value:= BadTurn;
       
   485 
       
   486         CheckTrace:= value;
       
   487     end;
       
   488 
       
   489     function Solve: LongWord;
       
   490     var A, B, D, T: hwFloat;
   431     var A, B, D, T: hwFloat;
   491         C: LongInt;
   432         C: LongInt;
   492     begin
   433     begin
   493         A:= hwSqr(cGravity) * _0_25;
   434         A:= hwSqr(cGravity) * _0_25;
   494         B:= - cGravity * (Targ.Y - hwRound(Me^.Y)) - _1;
   435         B:= - cGravity * (TY - MY) - _1;
   495         C:= sqr(Targ.Y - hwRound(Me^.Y)) + sqr(Targ.X - hwRound(Me^.X));
   436         C:= sqr(TY - MY) + sqr(TX - MX);
   496         D:= hwSqr(B) - (A * C * 4);
   437         D:= hwSqr(B) - (A * C * 4);
   497         if D.isNegative = false then
   438         if D.isNegative = false then
   498             begin
   439             begin
   499             D:= ( - B + hwSqrt(D)) * _0_5 / A;
   440             D:= ( - B + hwSqrt(D)) * _0_5 / A;
   500             if D.isNegative = false then
   441             if D.isNegative = false then
   502             else
   443             else
   503                 T:= _0;
   444                 T:= _0;
   504             Solve:= hwRound(T)
   445             Solve:= hwRound(T)
   505             end else Solve:= 0
   446             end else Solve:= 0
   506     end;
   447     end;
   507 
   448     
       
   449 function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
       
   450 //const tDelta = 24;
       
   451 var Vx, Vy: hwFloat;
       
   452     Score, EX, EY, valueResult: LongInt;
       
   453     TestTime: Longword;
       
   454     x, y, dY: hwFloat;
   508 begin
   455 begin
   509 valueResult:= BadTurn;
   456 valueResult:= BadTurn;
   510 ap.ExplR:= 0;
   457 ap.ExplR:= 0;
   511 
   458 
   512 if (Level > 2) then exit(BadTurn);
   459 if (Level > 2) then exit(BadTurn);
   513 
   460 
   514 TestTime:= Solve;
   461 TestTime:= Solve(Targ.X, Targ.Y, hwRound(Me^.X), hwRound(Me^.Y));
   515 
   462 
   516 if TestTime = 0 then exit(BadTurn);
   463 if TestTime = 0 then exit(BadTurn);
   517 
   464 
   518     Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime);
   465     Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime);
   519     Vy:= cGravity * (TestTime div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime);
   466     Vy:= cGravity * (TestTime div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime);
   520 
   467 
   521     Score:= CheckTrace;
   468     x:= Me^.X;
       
   469     y:= Me^.Y;
       
   470     dY:= -Vy;
       
   471 
       
   472     repeat
       
   473         x:= x + Vx;
       
   474         y:= y + dY;
       
   475         dY:= dY + cGravity;
       
   476         EX:= hwRound(x);
       
   477         EY:= hwRound(y);
       
   478     until TestCollExcludingMe(Me, EX, EY, 5) or (EY > cWaterLine);
       
   479 
       
   480     if (EY < cWaterLine) and (not dY.isNegative) then
       
   481         begin
       
   482         Score:= RateExplosion(Me, EX, EY, 91);
       
   483         if (Score = 0) then
       
   484             if (dY > _0_15) then
       
   485                 Score:= - abs(Targ.Y - EY) div 32
       
   486             else
       
   487                 Score:= BadTurn
       
   488         else if (Score < 0) then Score:= BadTurn
       
   489         end
       
   490     else
       
   491         Score:= BadTurn;
       
   492 
   522     if valueResult < Score then
   493     if valueResult < Score then
   523         begin
   494         begin
   524         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
   495         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
   525         ap.Power:= 1;
   496         ap.Power:= 1;
   526         ap.ExplR:= 100;
   497         ap.ExplR:= 100;