17 *) |
17 *) |
18 |
18 |
19 unit uAIAmmoTests; |
19 unit uAIAmmoTests; |
20 interface |
20 interface |
21 uses SDLh, uGears, uConsts, uFloat; |
21 uses SDLh, uGears, uConsts, uFloat; |
22 |
22 const amtest_OnTurn = $00000001; |
23 function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
23 |
24 function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
24 type TAttackParams = record |
25 function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
25 Time: Longword; |
26 function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
26 Angle, Power: LongInt; |
27 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
27 ExplX, ExplY, ExplR: LongInt; |
28 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
28 AttackPutX, AttackPutY: LongInt; |
29 |
29 end; |
30 type TAmmoTestProc = function (Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
30 |
31 const AmmoTests: array[TAmmoType] of TAmmoTestProc = |
31 function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
|
32 function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
|
33 function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
|
34 function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
|
35 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
|
36 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
|
37 function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
|
38 |
|
39 type TAmmoTestProc = function (Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
|
40 TAmmoTest = record |
|
41 proc: TAmmoTestProc; |
|
42 flags: Longword; |
|
43 end; |
|
44 |
|
45 const AmmoTests: array[TAmmoType] of TAmmoTest = |
32 ( |
46 ( |
33 {amGrenade} @TestGrenade, |
47 (proc: @TestGrenade; flags: 0), // amGrenade |
34 {amClusterBomb} nil, |
48 (proc: nil; flags: 0), // amClusterBomb |
35 {amBazooka} @TestBazooka, |
49 (proc: @TestBazooka; flags: 0), // amBazooka |
36 {amUFO} nil, |
50 (proc: nil; flags: 0), // amUFO |
37 {amShotgun} @TestShotgun, |
51 (proc: @TestShotgun; flags: 0), // amShotgun |
38 {amPickHammer} nil, |
52 (proc: nil; flags: 0), // amPickHammer |
39 {amSkip} nil, |
53 (proc: nil; flags: 0), // amSkip |
40 {amRope} nil, |
54 (proc: nil; flags: 0), // amRope |
41 {amMine} nil, |
55 (proc: nil; flags: 0), // amMine |
42 {amDEagle} @TestDesertEagle, |
56 (proc: @TestDesertEagle; flags: 0), // amDEagle |
43 {amDynamite} nil, |
57 (proc: nil; flags: 0), // amDynamite |
44 {amFirePunch} @TestFirePunch, |
58 (proc: @TestFirePunch; flags: 0), // amFirePunch |
45 {amBaseballBat} @TestBaseballBat, |
59 (proc: @TestBaseballBat; flags: 0), // amBaseballBat |
46 {amParachute} nil, |
60 (proc: nil; flags: 0), // amParachute |
47 {amAirAttack} nil, |
61 (proc: @TestAirAttack; flags: amtest_OnTurn), // amAirAttack |
48 {amMineStrike} nil, |
62 (proc: nil; flags: 0), // amMineStrike |
49 {amBlowTorch} nil, |
63 (proc: nil; flags: 0), // amBlowTorch |
50 {amGirder} nil, |
64 (proc: nil; flags: 0), // amGirder |
51 {amTeleport} nil, |
65 (proc: nil; flags: amtest_OnTurn), // amTeleport |
52 {amSwitch} nil |
66 (proc: nil; flags: 0) // amSwitch |
53 ); |
67 ); |
54 |
68 |
55 const BadTurn = Low(LongInt) div 4; |
69 const BadTurn = Low(LongInt) div 4; |
56 |
|
57 |
70 |
58 implementation |
71 implementation |
59 uses uMisc, uAIMisc, uLand; |
72 uses uMisc, uAIMisc, uLand; |
60 |
73 |
61 function Metric(x1, y1, x2, y2: LongInt): LongInt; |
74 function Metric(x1, y1, x2, y2: LongInt): LongInt; |
62 begin |
75 begin |
63 Metric:= abs(x1 - x2) + abs(y1 - y2) |
76 Metric:= abs(x1 - x2) + abs(y1 - y2) |
64 end; |
77 end; |
65 |
78 |
66 function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
79 function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
67 var Vx, Vy, r: hwFloat; |
80 var Vx, Vy, r: hwFloat; |
68 rTime: LongInt; |
81 rTime: LongInt; |
69 Score, EX, EY: LongInt; |
82 Score, EX, EY: LongInt; |
70 Result: LongInt; |
83 Result: LongInt; |
71 |
84 |
147 end; |
160 end; |
148 |
161 |
149 begin |
162 begin |
150 Result:= BadTurn; |
163 Result:= BadTurn; |
151 TestTime:= 0; |
164 TestTime:= 0; |
152 ExplR:= 0; |
165 ap.ExplR:= 0; |
153 repeat |
166 repeat |
154 inc(TestTime, 1000); |
167 inc(TestTime, 1000); |
155 Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta); |
168 Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta); |
156 Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime + tDelta); |
169 Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime + tDelta); |
157 r:= Distance(Vx, Vy); |
170 r:= Distance(Vx, Vy); |
158 if not (r > _1) then |
171 if not (r > _1) then |
159 begin |
172 begin |
160 Score:= CheckTrace; |
173 Score:= CheckTrace; |
161 if Result < Score then |
174 if Result < Score then |
162 begin |
175 begin |
163 Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level)); |
176 ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level)); |
164 Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 15); |
177 ap.Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 15); |
165 Time:= TestTime; |
178 ap.Time:= TestTime; |
166 ExplR:= 100; |
179 ap.ExplR:= 100; |
167 ExplX:= EX; |
180 ap.ExplX:= EX; |
168 ExplY:= EY; |
181 ap.ExplY:= EY; |
169 Result:= Score |
182 Result:= Score |
170 end; |
183 end; |
171 end |
184 end |
172 until (TestTime = 4000); |
185 until (TestTime = 4000); |
173 TestGrenade:= Result |
186 TestGrenade:= Result |
174 end; |
187 end; |
175 |
188 |
176 function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
189 function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
177 var Vx, Vy, x, y: hwFloat; |
190 var Vx, Vy, x, y: hwFloat; |
178 rx, ry, Result: LongInt; |
191 rx, ry, Result: LongInt; |
179 begin |
192 begin |
180 ExplR:= 0; |
193 ap.ExplR:= 0; |
181 Time:= 0; |
194 ap.Time:= 0; |
182 Power:= 1; |
195 ap.Power:= 1; |
183 if Metric(hwRound(Me^.X), hwRound(Me^.Y), Targ.X, Targ.Y) < 80 then |
196 if Metric(hwRound(Me^.X), hwRound(Me^.Y), Targ.X, Targ.Y) < 80 then |
184 exit(BadTurn); |
197 exit(BadTurn); |
185 Vx:= (int2hwFloat(Targ.X) - Me^.X) * _1div1024; |
198 Vx:= (int2hwFloat(Targ.X) - Me^.X) * _1div1024; |
186 Vy:= (int2hwFloat(Targ.Y) - Me^.Y) * _1div1024; |
199 Vy:= (int2hwFloat(Targ.Y) - Me^.Y) * _1div1024; |
187 x:= Me^.X; |
200 x:= Me^.X; |
188 y:= Me^.Y; |
201 y:= Me^.Y; |
189 Angle:= DxDy2AttackAngle(Vx, -Vy); |
202 ap.Angle:= DxDy2AttackAngle(Vx, -Vy); |
190 repeat |
203 repeat |
191 x:= x + vX; |
204 x:= x + vX; |
192 y:= y + vY; |
205 y:= y + vY; |
193 rx:= hwRound(x); |
206 rx:= hwRound(x); |
194 ry:= hwRound(y); |
207 ry:= hwRound(y); |
203 end |
216 end |
204 until (Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 4) or (x < _0) or (y < _0) or (x > _2048) or (y > _1024); |
217 until (Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 4) or (x < _0) or (y < _0) or (x > _2048) or (y > _1024); |
205 TestShotgun:= BadTurn |
218 TestShotgun:= BadTurn |
206 end; |
219 end; |
207 |
220 |
208 function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
221 function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
209 var Vx, Vy, x, y, t: hwFloat; |
222 var Vx, Vy, x, y, t: hwFloat; |
210 d: Longword; |
223 d: Longword; |
211 Result: LongInt; |
224 Result: LongInt; |
212 begin |
225 begin |
213 ExplR:= 0; |
226 ap.ExplR:= 0; |
214 Time:= 0; |
227 ap.Time:= 0; |
215 Power:= 1; |
228 ap.Power:= 1; |
216 if Abs(hwRound(Me^.X) - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) < 80 then |
229 if Abs(hwRound(Me^.X) - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) < 80 then |
217 exit(BadTurn); |
230 exit(BadTurn); |
218 t:= _0_5 / Distance(int2hwFloat(Targ.X) - Me^.X, int2hwFloat(Targ.Y) - Me^.Y); |
231 t:= _0_5 / Distance(int2hwFloat(Targ.X) - Me^.X, int2hwFloat(Targ.Y) - Me^.Y); |
219 Vx:= (int2hwFloat(Targ.X) - Me^.X) * t; |
232 Vx:= (int2hwFloat(Targ.X) - Me^.X) * t; |
220 Vy:= (int2hwFloat(Targ.Y) - Me^.Y) * t; |
233 Vy:= (int2hwFloat(Targ.Y) - Me^.Y) * t; |
221 x:= Me^.X; |
234 x:= Me^.X; |
222 y:= Me^.Y; |
235 y:= Me^.Y; |
223 Angle:= DxDy2AttackAngle(Vx, -Vy); |
236 ap.Angle:= DxDy2AttackAngle(Vx, -Vy); |
224 d:= 0; |
237 d:= 0; |
225 repeat |
238 repeat |
226 x:= x + vX; |
239 x:= x + vX; |
227 y:= y + vY; |
240 y:= y + vY; |
228 if ((hwRound(x) and $FFFFF800) = 0)and((hwRound(y) and $FFFFFC00) = 0) |
241 if ((hwRound(x) and $FFFFF800) = 0)and((hwRound(y) and $FFFFFC00) = 0) |
229 and (Land[hwRound(y), hwRound(x)] <> 0) then inc(d); |
242 and (Land[hwRound(y), hwRound(x)] <> 0) then inc(d); |
230 until (Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 4) or (x < _0) or (y < _0) or (x > _2048) or (y > _1024) or (d > 200); |
243 until (Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 4) or (x < _0) or (y < _0) or (x > _2048) or (y > _1024) or (d > 200); |
231 if Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 3 then Result:= max(0, (4 - d div 50) * 7 * 1024) |
244 if Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 3 then Result:= max(0, (4 - d div 50) * 7 * 1024) |
232 else Result:= Low(LongInt); |
245 else Result:= BadTurn; |
233 TestDesertEagle:= Result |
246 TestDesertEagle:= Result |
234 end; |
247 end; |
235 |
248 |
236 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
249 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
237 var Result: LongInt; |
250 var Result: LongInt; |
238 begin |
251 begin |
239 ExplR:= 0; |
252 ap.ExplR:= 0; |
240 if (Level > 2) and not (Abs(hwRound(Me^.X) - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) < 25) then |
253 if (Level > 2) or (Abs(hwRound(Me^.X) - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) > 25) then |
241 exit(BadTurn); |
254 exit(BadTurn); |
242 |
255 |
243 Time:= 0; |
256 ap.Time:= 0; |
244 Power:= 1; |
257 ap.Power:= 1; |
245 if (Targ.X) - hwRound(Me^.X) >= 0 then Angle:= cMaxAngle div 4 |
258 if (Targ.X) - hwRound(Me^.X) >= 0 then ap.Angle:= cMaxAngle div 4 |
246 else Angle:= - cMaxAngle div 4; |
259 else ap.Angle:= - cMaxAngle div 4; |
247 Result:= RateShove(Me, hwRound(Me^.X) + 10 * hwSign(int2hwFloat(Targ.X) - Me^.X), hwRound(Me^.Y), 15, 30); |
260 Result:= RateShove(Me, hwRound(Me^.X) + 10 * hwSign(int2hwFloat(Targ.X) - Me^.X), hwRound(Me^.Y), 15, 30); |
248 if Result <= 0 then Result:= BadTurn else inc(Result); |
261 if Result <= 0 then Result:= BadTurn else inc(Result); |
249 TestBaseballBat:= Result |
262 TestBaseballBat:= Result |
250 end; |
263 end; |
251 |
264 |
252 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; |
265 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
253 var i, Result: LongInt; |
266 var i, Result: LongInt; |
254 begin |
267 begin |
255 ExplR:= 0; |
268 ap.ExplR:= 0; |
256 Time:= 0; |
269 ap.Time:= 0; |
257 Power:= 1; |
270 ap.Power:= 1; |
258 Angle:= 0; |
271 ap.Angle:= 0; |
259 if (Abs(hwRound(Me^.X) - Targ.X) > 25) or (Abs(hwRound(Me^.Y) - 50 - Targ.Y) > 50) then |
272 if (Abs(hwRound(Me^.X) - Targ.X) > 25) or (Abs(hwRound(Me^.Y) - 50 - Targ.Y) > 50) then |
260 exit(BadTurn); |
273 exit(BadTurn); |
261 |
274 |
262 Result:= 0; |
275 Result:= 0; |
263 for i:= 0 to 4 do |
276 for i:= 0 to 4 do |
265 hwRound(Me^.Y) - 20 * i - 5, 10, 30); |
278 hwRound(Me^.Y) - 20 * i - 5, 10, 30); |
266 if Result <= 0 then Result:= BadTurn else inc(Result); |
279 if Result <= 0 then Result:= BadTurn else inc(Result); |
267 TestFirePunch:= Result |
280 TestFirePunch:= Result |
268 end; |
281 end; |
269 |
282 |
|
283 function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; |
|
284 var X, Y, dY: hwFloat; |
|
285 b: array[0..9] of boolean; |
|
286 dmg: array[0..9] of LongInt; |
|
287 fexit: boolean; |
|
288 i, t, Result: LongInt; |
|
289 begin |
|
290 ap.ExplR:= 0; |
|
291 ap.Time:= 0; |
|
292 ap.AttackPutX:= Targ.X; |
|
293 ap.AttackPutY:= Targ.Y; |
|
294 |
|
295 X:= int2hwFloat(Targ.X - 135); |
|
296 X:= X - cBombsSpeed * hwSqrt(int2hwFloat((Targ.Y + 128) * 2) / cGravity); |
|
297 Y:= -_128; |
|
298 dY:= _0; |
|
299 |
|
300 for i:= 0 to 9 do |
|
301 begin |
|
302 b[i]:= true; |
|
303 dmg[i]:= 0 |
|
304 end; |
|
305 Result:= 0; |
|
306 |
|
307 repeat |
|
308 X:= X + cBombsSpeed; |
|
309 Y:= Y + dY; |
|
310 dY:= dY + cGravity; |
|
311 fexit:= true; |
|
312 |
|
313 for i:= 0 to 9 do |
|
314 if b[i] then |
|
315 begin |
|
316 fexit:= false; |
|
317 if TestColl(hwRound(X) + i * 30, hwRound(Y), 4) then |
|
318 begin |
|
319 b[i]:= false; |
|
320 dmg[i]:= RateExplosion(Me, hwRound(X) + i * 30, hwRound(Y), 58) |
|
321 // 58 (instead of 60) for better prediction (hh moves after explosion of one of the rockets) |
|
322 end |
|
323 end; |
|
324 until fexit or (Y > _1024); |
|
325 |
|
326 for i:= 0 to 5 do inc(Result, dmg[i]); |
|
327 t:= Result; |
|
328 ap.AttackPutX:= Targ.X - 60; |
|
329 |
|
330 for i:= 0 to 3 do |
|
331 begin |
|
332 dec(t, dmg[i]); |
|
333 inc(t, dmg[i + 6]); |
|
334 if t > Result then |
|
335 begin |
|
336 Result:= t; |
|
337 ap.AttackPutX:= Targ.X - 30 + i * 30 |
|
338 end |
|
339 end; |
|
340 |
|
341 if Result <= 0 then Result:= BadTurn; |
|
342 TestAirAttack:= Result |
|
343 end; |
|
344 |
270 end. |
345 end. |