46 end; |
51 end; |
47 TBonus = record |
52 TBonus = record |
48 X, Y: LongInt; |
53 X, Y: LongInt; |
49 Radius: LongInt; |
54 Radius: LongInt; |
50 Score: LongInt; |
55 Score: LongInt; |
51 end; |
56 end; |
|
57 |
|
58 TBonuses = record |
|
59 activity: boolean; |
|
60 Count : LongInt; |
|
61 ar : array[0..Pred(MAXBONUS)] of TBonus; |
|
62 end; |
|
63 |
|
64 Twalkbonuses = record |
|
65 Count: Longword; |
|
66 ar: array[0..Pred(MAXBONUS div 8)] of TBonus; // don't use too many |
|
67 end; |
52 |
68 |
53 procedure initModule; |
69 procedure initModule; |
54 procedure freeModule; |
70 procedure freeModule; |
55 |
71 |
56 procedure FillTargets; |
72 procedure FillTargets; |
|
73 procedure ResetTargets; inline; |
57 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline; |
74 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline; |
58 procedure FillBonuses(isAfterAttack: boolean); |
75 procedure FillBonuses(isAfterAttack: boolean); |
59 procedure AwareOfExplosion(x, y, r: LongInt); inline; |
76 procedure AwareOfExplosion(x, y, r: LongInt); inline; |
60 |
77 |
61 function RatePlace(Gear: PGear): LongInt; |
78 function RatePlace(Gear: PGear): LongInt; |
|
79 function CheckWrap(x: real): real; inline; |
62 function TestColl(x, y, r: LongInt): boolean; inline; |
80 function TestColl(x, y, r: LongInt): boolean; inline; |
63 function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; |
81 function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; |
64 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; |
82 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; |
65 function TraceShoveFall(x, y, dX, dY: Real): LongInt; |
|
66 |
83 |
67 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; |
84 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; |
68 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
85 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline; |
69 function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
86 function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
|
87 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
70 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
88 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
71 function RateHammer(Me: PGear): LongInt; |
89 function RateHammer(Me: PGear): LongInt; |
72 |
90 |
73 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; |
91 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; |
74 function AIrndSign(num: LongInt): LongInt; |
92 function AIrndSign(num: LongInt): LongInt; inline; |
|
93 function AIrndOffset(targ: TTarget; Level: LongWord): LongInt; inline; |
75 |
94 |
76 var ThinkingHH: PGear; |
95 var ThinkingHH: PGear; |
77 Targets: TTargets; |
96 Targets: TTargets; |
78 |
97 |
79 bonuses: record |
98 bonuses: TBonuses; |
80 Count: Longword; |
99 |
81 ar: array[0..Pred(MAXBONUS)] of TBonus; |
100 walkbonuses: Twalkbonuses; |
82 end; |
|
83 |
|
84 walkbonuses: record |
|
85 Count: Longword; |
|
86 ar: array[0..Pred(MAXBONUS div 8)] of TBonus; // don't use too many |
|
87 end; |
|
88 |
101 |
89 const KillScore = 200; |
102 const KillScore = 200; |
90 var friendlyfactor: LongInt = 300; |
103 var friendlyfactor: LongInt = 300; |
|
104 var dmgMod: real = 1.0; |
91 |
105 |
92 implementation |
106 implementation |
93 uses uCollisions, uVariables, uUtils, uLandTexture, uGearsUtils; |
107 uses uCollisions, uVariables, uUtils, uGearsUtils; |
94 |
108 |
95 var |
109 var |
96 KnownExplosion: record |
110 KnownExplosion: record |
97 X, Y, Radius: LongInt |
111 X, Y, Radius: LongInt |
98 end = (X: 0; Y: 0; Radius: 0); |
112 end = (X: 0; Y: 0; Radius: 0); |
99 |
113 |
|
114 procedure ResetTargets; inline; |
|
115 var i: LongWord; |
|
116 begin |
|
117 if Targets.reset then |
|
118 for i:= 0 to Targets.Count do |
|
119 Targets.ar[i].dead:= false; |
|
120 Targets.reset:= false; |
|
121 end; |
100 procedure FillTargets; |
122 procedure FillTargets; |
101 var i, t: Longword; |
123 var //i, t: Longword; |
102 f, e: LongInt; |
124 f, e: LongInt; |
|
125 Gear: PGear; |
103 begin |
126 begin |
104 Targets.Count:= 0; |
127 Targets.Count:= 0; |
|
128 Targets.reset:= false; |
105 f:= 0; |
129 f:= 0; |
106 e:= 0; |
130 e:= 0; |
107 for t:= 0 to Pred(TeamsCount) do |
131 Gear:= GearsList; |
108 with TeamsArray[t]^ do |
132 while Gear <> nil do |
109 if not hasGone then |
133 begin |
110 begin |
134 if (((Gear^.Kind = gtHedgehog) and |
111 for i:= 0 to cMaxHHIndex do |
135 (Gear <> ThinkingHH) and |
112 if (Hedgehogs[i].Gear <> nil) |
136 (Gear^.Health > Gear^.Damage) and |
113 and (Hedgehogs[i].Gear <> ThinkingHH) |
137 (not Gear^.Hedgehog^.Team^.hasgone)) or |
114 and (Hedgehogs[i].Gear^.Health > Hedgehogs[i].Gear^.Damage) |
138 ((Gear^.Kind = gtExplosives) and |
115 then |
139 (Gear^.Health > Gear^.Damage)) or |
116 begin |
140 ((Gear^.Kind = gtMine) and |
117 with Targets.ar[Targets.Count], Hedgehogs[i] do |
141 (Gear^.Health = 0) and |
118 begin |
142 (Gear^.Damage < 35)) |
119 skip:= false; |
143 ) and |
120 Point.X:= hwRound(Gear^.X); |
144 (Targets.Count < 256) then |
121 Point.Y:= hwRound(Gear^.Y); |
145 begin |
122 if Clan <> CurrentTeam^.Clan then |
146 with Targets.ar[Targets.Count] do |
123 begin |
147 begin |
124 Score:= Gear^.Health - Gear^.Damage; |
148 skip:= false; |
125 inc(e) |
149 dead:= false; |
126 end else |
150 Kind:= Gear^.Kind; |
127 begin |
151 Radius:= Gear^.Radius; |
128 Score:= Gear^.Damage - Gear^.Health; |
152 Density:= hwFloat2Float(Gear^.Density)/3; |
129 inc(f) |
153 State:= Gear^.State; |
130 end |
154 matters:= (Gear^.AIHints and aihDoesntMatter) = 0; |
131 end; |
155 |
132 inc(Targets.Count) |
156 Point.X:= hwRound(Gear^.X); |
|
157 Point.Y:= hwRound(Gear^.Y); |
|
158 if (Gear^.Kind = gtHedgehog) then |
|
159 begin |
|
160 if (Gear^.Hedgehog^.Team^.Clan = CurrentTeam^.Clan) then |
|
161 begin |
|
162 Score:= Gear^.Damage - Gear^.Health; |
|
163 inc(f) |
|
164 end |
|
165 else |
|
166 begin |
|
167 Score:= Gear^.Health - Gear^.Damage; |
|
168 inc(e) |
133 end; |
169 end; |
|
170 end |
|
171 else if Gear^.Kind = gtExplosives then |
|
172 Score:= Gear^.Health - Gear^.Damage |
|
173 else if Gear^.Kind = gtMine then |
|
174 Score:= max(0,35-Gear^.Damage); |
134 end; |
175 end; |
|
176 inc(Targets.Count) |
|
177 end; |
|
178 Gear:= Gear^.NextGear |
|
179 end; |
135 |
180 |
136 if e > f then friendlyfactor:= 300 + (e - f) * 30 |
181 if e > f then friendlyfactor:= 300 + (e - f) * 30 |
137 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e)) |
182 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e)) |
138 end; |
183 end; |
139 |
184 |
250 inc(rate, Score * (Radius - r)) |
333 inc(rate, Score * (Radius - r)) |
251 end; |
334 end; |
252 RatePlace:= rate; |
335 RatePlace:= rate; |
253 end; |
336 end; |
254 |
337 |
|
338 function CheckWrap(x: real): real; inline; |
|
339 begin |
|
340 if WorldEdge = weWrap then |
|
341 if (x < leftX) then |
|
342 x:= x + (rightX - leftX) |
|
343 else if x > rightX then |
|
344 x:= x - (rightX - leftX); |
|
345 CheckWrap:= x; |
|
346 end; |
|
347 |
|
348 function CheckBounds(x, y, r: Longint): boolean; inline; |
|
349 begin |
|
350 CheckBounds := (((x-r) and LAND_WIDTH_MASK) = 0) and |
|
351 (((x+r) and LAND_WIDTH_MASK) = 0) and |
|
352 (((y-r) and LAND_HEIGHT_MASK) = 0) and |
|
353 (((y+r) and LAND_HEIGHT_MASK) = 0); |
|
354 end; |
|
355 |
|
356 |
|
357 function TestCollWithEverything(x, y, r: LongInt): boolean; inline; |
|
358 begin |
|
359 if not CheckBounds(x, y, r) then |
|
360 exit(false); |
|
361 |
|
362 if (Land[y-r, x-r] <> 0) or |
|
363 (Land[y+r, x-r] <> 0) or |
|
364 (Land[y-r, x+r] <> 0) or |
|
365 (Land[y+r, x+r] <> 0) then |
|
366 exit(true); |
|
367 |
|
368 TestCollWithEverything := false; |
|
369 end; |
|
370 |
|
371 function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; |
|
372 begin |
|
373 if not CheckBounds(x, y, r) then |
|
374 exit(false); |
|
375 |
|
376 if (Land[y-r, x-r] > lfAllObjMask) or |
|
377 (Land[y+r, x-r] > lfAllObjMask) or |
|
378 (Land[y-r, x-r] > lfAllObjMask) or |
|
379 (Land[y+r, x+r] > lfAllObjMask) then |
|
380 exit(true); |
|
381 |
|
382 TestCollExcludingObjects:= false; |
|
383 end; |
|
384 |
|
385 function TestColl(x, y, r: LongInt): boolean; inline; |
|
386 begin |
|
387 if not CheckBounds(x, y, r) then |
|
388 exit(false); |
|
389 |
|
390 if (Land[y-r, x-r] and lfNotCurHogCrate <> 0) or |
|
391 (Land[y+r, x-r] and lfNotCurHogCrate <> 0) or |
|
392 (Land[y+r, x-r] and lfNotCurHogCrate <> 0) or |
|
393 (Land[y+r, x+r] and lfNotCurHogCrate <> 0) then |
|
394 exit(true); |
|
395 |
|
396 TestColl:= false; |
|
397 end; |
|
398 |
|
399 |
255 // Wrapper to test various approaches. If it works reasonably, will just replace. |
400 // Wrapper to test various approaches. If it works reasonably, will just replace. |
256 // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with... |
401 // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with... |
257 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; |
402 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; |
258 var MeX, MeY: LongInt; |
403 var MeX, MeY: LongInt; |
259 begin |
404 begin |
260 if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then |
405 if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then |
261 begin |
406 begin |
262 MeX:= hwRound(Me^.X); |
407 MeX:= hwRound(Me^.X); |
263 MeY:= hwRound(Me^.Y); |
408 MeY:= hwRound(Me^.Y); |
264 // We are still inside the hog. Skip radius test |
409 // We are still inside the hog. Skip radius test |
265 if ((((x-MeX)*(x-MeX)) + ((y-MeY)*(y-MeY))) < 256) and ((Land[y, x] and $FF00) = 0) then |
410 if ((sqr(x-MeX) + sqr(y-MeY)) < 256) and (Land[y, x] and lfObjMask = 0) then |
266 exit(false); |
411 exit(false); |
267 end; |
412 end; |
268 TestCollExcludingMe:= TestColl(x, y, r) |
413 TestCollExcludingMe:= TestCollWithEverything(x, y, r) |
269 end; |
414 end; |
270 |
415 |
271 function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; |
416 |
272 var b: boolean; |
417 |
273 begin |
418 function TraceFall(eX, eY: LongInt; var x, y: Real; dX, dY: Real; r: LongWord; Target: TTarget): LongInt; |
274 b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] and $FF00 <> 0); |
|
275 if b then |
|
276 exit(true); |
|
277 |
|
278 b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] and $FF00 <> 0); |
|
279 if b then |
|
280 exit(true); |
|
281 |
|
282 b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] and $FF00 <> 0); |
|
283 if b then |
|
284 exit(true); |
|
285 |
|
286 b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] and $FF00 <> 0); |
|
287 if b then |
|
288 exit(true); |
|
289 |
|
290 TestCollExcludingObjects:= false; |
|
291 end; |
|
292 |
|
293 function TestColl(x, y, r: LongInt): boolean; inline; |
|
294 var b: boolean; |
|
295 begin |
|
296 b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] and $FF7F <> 0); |
|
297 if b then |
|
298 exit(true); |
|
299 |
|
300 b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] and $FF7F <> 0); |
|
301 if b then |
|
302 exit(true); |
|
303 |
|
304 b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] and $FF7F <> 0); |
|
305 if b then |
|
306 exit(true); |
|
307 |
|
308 b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] and $FF7F <> 0); |
|
309 if b then |
|
310 exit(true); |
|
311 |
|
312 TestColl:= false; |
|
313 end; |
|
314 |
|
315 function TestCollWithLand(x, y, r: LongInt): boolean; inline; |
|
316 var b: boolean; |
|
317 begin |
|
318 b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] > 255); |
|
319 if b then |
|
320 exit(true); |
|
321 |
|
322 b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] > 255); |
|
323 if b then |
|
324 exit(true); |
|
325 |
|
326 b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] > 255); |
|
327 if b then |
|
328 exit(true); |
|
329 |
|
330 b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] > 255); |
|
331 if b then |
|
332 exit(true); |
|
333 |
|
334 TestCollWithLand:= false; |
|
335 end; |
|
336 |
|
337 function TraceFall(eX, eY: LongInt; x, y, dX, dY: Real; r: LongWord): LongInt; |
|
338 var skipLandCheck: boolean; |
419 var skipLandCheck: boolean; |
339 rCorner: real; |
420 rCorner, dxdy, odX, odY: real; |
340 dmg: LongInt; |
421 dmg: LongInt; |
341 begin |
422 begin |
|
423 odX:= dX; |
|
424 odY:= dY; |
342 skipLandCheck:= true; |
425 skipLandCheck:= true; |
343 if x - eX < 0 then dX:= -dX; |
|
344 if y - eY < 0 then dY:= -dY; |
|
345 // ok. attempt approximate search for an unbroken trajectory into water. if it continues far enough, assume out of map |
426 // ok. attempt approximate search for an unbroken trajectory into water. if it continues far enough, assume out of map |
346 rCorner:= r * 0.75; |
427 rCorner:= r * 0.75; |
347 while true do |
428 while true do |
348 begin |
429 begin |
|
430 x:= CheckWrap(x); |
349 x:= x + dX; |
431 x:= x + dX; |
350 y:= y + dY; |
432 y:= y + dY; |
351 dY:= dY + cGravityf; |
433 dY:= dY + cGravityf; |
352 skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner)); |
434 skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner)); |
353 if not skipLandCheck and TestCollWithLand(trunc(x), trunc(y), cHHRadius) then |
435 if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then |
354 begin |
436 with Target do |
355 if 0.4 < dY then |
437 begin |
356 begin |
438 if (Kind = gtHedgehog) and (0.4 < dY) then |
357 dmg := 1 + trunc((abs(dY) - 0.4) * 70); |
439 begin |
358 if dmg >= 1 then |
440 dmg := 1 + trunc((dY - 0.4) * 70); |
359 exit(dmg); |
441 exit(dmg) |
|
442 end |
|
443 else |
|
444 begin |
|
445 dxdy:= abs(dX)+abs(dY); |
|
446 if ((Kind = gtMine) and (dxdy > 0.35)) or |
|
447 ((Kind = gtExplosives) and |
|
448 (((State and gstTmpFlag <> 0) and (dxdy > 0.35)) or |
|
449 ((State and gstTmpFlag = 0) and |
|
450 ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and |
|
451 (abs(odX) > 0.02))) and (dxdy > 0.35)))) then |
|
452 begin |
|
453 dmg := trunc(dxdy * 25); |
|
454 exit(dmg) |
|
455 end |
|
456 else if (Kind = gtExplosives) and (not(abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then |
|
457 begin |
|
458 dmg := trunc(dy * 70); |
|
459 exit(dmg) |
|
460 end |
|
461 end; |
|
462 exit(0) |
360 end; |
463 end; |
361 exit(0) |
464 if CheckCoordInWater(round(x), round(y)) then exit(-1) |
362 end; |
465 end |
363 if (y > cWaterLine) or (x > 4096) or (x < 0) then |
466 end; |
364 exit(-1); |
467 |
365 end; |
468 function TraceShoveFall(var x, y: Real; dX, dY: Real; Target: TTarget): LongInt; |
366 end; |
|
367 |
|
368 function TraceShoveFall(x, y, dX, dY: Real): LongInt; |
|
369 var dmg: LongInt; |
469 var dmg: LongInt; |
370 begin |
470 dxdy, odX, odY: real; |
|
471 begin |
|
472 odX:= dX; |
|
473 odY:= dY; |
371 //v:= random($FFFFFFFF); |
474 //v:= random($FFFFFFFF); |
372 while true do |
475 while true do |
373 begin |
476 begin |
|
477 x:= CheckWrap(x); |
374 x:= x + dX; |
478 x:= x + dX; |
375 y:= y + dY; |
479 y:= y + dY; |
376 dY:= dY + cGravityf; |
480 dY:= dY + cGravityf; |
377 |
481 |
378 { if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then |
482 { if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then |
379 begin |
483 begin |
380 LandPixels[trunc(y), trunc(x)]:= v; |
484 LandPixels[trunc(y), trunc(x)]:= v; |
381 UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true); |
485 UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true); |
382 end;} |
486 end;} |
383 |
487 |
384 |
488 if TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then |
385 // consider adding dX/dY calc here for fall damage |
489 with Target do |
386 if TestCollExcludingObjects(trunc(x), trunc(y), cHHRadius) then |
490 begin |
387 begin |
491 if (Kind = gtHedgehog) and (0.4 < dY) then |
388 if 0.4 < dY then |
492 begin |
389 begin |
493 dmg := trunc((dY - 0.4) * 70); |
390 dmg := 1 + trunc((abs(dY) - 0.4) * 70); |
|
391 if dmg >= 1 then |
|
392 exit(dmg); |
494 exit(dmg); |
393 end; |
495 end |
|
496 else |
|
497 begin |
|
498 dxdy:= abs(dX)+abs(dY); |
|
499 if ((Kind = gtMine) and (dxdy > 0.4)) or |
|
500 ((Kind = gtExplosives) and |
|
501 (((State and gstTmpFlag <> 0) and (dxdy > 0.4)) or |
|
502 ((State and gstTmpFlag = 0) and |
|
503 ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and |
|
504 (abs(odX) > 0.02))) and (dxdy > 0.35)))) then |
|
505 begin |
|
506 dmg := trunc(dxdy * 50); |
|
507 exit(dmg) |
|
508 end |
|
509 else if (Kind = gtExplosives) and (not(abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then |
|
510 begin |
|
511 dmg := trunc(dy * 70); |
|
512 exit(dmg) |
|
513 end |
|
514 end; |
394 exit(0) |
515 exit(0) |
395 end; |
516 end; |
396 if (y > cWaterLine) or (x > 4096) or (x < 0) then |
517 if CheckCoordInWater(round(x), round(y)) then |
397 // returning -1 for drowning so it can be considered in the Rate routine |
518 // returning -1 for drowning so it can be considered in the Rate routine |
398 exit(-1) |
519 exit(-1) |
399 end; |
520 end; |
400 end; |
521 end; |
401 |
522 |
402 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; |
523 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; |
403 begin |
524 begin |
404 RateExplosion:= RateExplosion(Me, x, y, r, 0); |
525 RateExplosion:= RealRateExplosion(Me, x, y, r, 0); |
405 end; |
526 ResetTargets; |
406 |
527 end; |
407 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
528 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline; |
408 var i, fallDmg, dmg, dmgBase, rate, erasure: LongInt; |
529 begin |
409 dX, dY, dmgMod: real; |
530 RateExplosion:= RealRateExplosion(Me, x, y, r, Flags); |
410 begin |
531 ResetTargets; |
|
532 end; |
|
533 |
|
534 function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
|
535 var i, fallDmg, dmg, dmgBase, rate, subrate, erasure: LongInt; |
|
536 pX, pY, dX, dY: real; |
|
537 hadSkips: boolean; |
|
538 begin |
|
539 x:= round(CheckWrap(real(x))); |
411 fallDmg:= 0; |
540 fallDmg:= 0; |
412 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; |
|
413 rate:= 0; |
541 rate:= 0; |
414 // add our virtual position |
542 // add our virtual position |
415 with Targets.ar[Targets.Count] do |
543 with Targets.ar[Targets.Count] do |
416 begin |
544 begin |
417 Point.x:= hwRound(Me^.X); |
545 Point.x:= hwRound(Me^.X); |
418 Point.y:= hwRound(Me^.Y); |
546 Point.y:= hwRound(Me^.Y); |
|
547 skip:= false; |
|
548 matters:= true; |
|
549 Kind:= gtHedgehog; |
|
550 Density:= 1; |
|
551 Radius:= cHHRadius; |
419 Score:= - ThinkingHH^.Health |
552 Score:= - ThinkingHH^.Health |
420 end; |
553 end; |
421 // rate explosion |
554 // rate explosion |
422 dmgBase:= r + cHHRadius div 2; |
555 |
423 if (Flags and afErasesLand <> 0) and (GameFlags and gfSolidLand = 0) then erasure:= r |
556 if (Flags and afErasesLand <> 0) and (GameFlags and gfSolidLand = 0) then erasure:= r |
424 else erasure:= 0; |
557 else erasure:= 0; |
|
558 |
|
559 hadSkips:= false; |
|
560 |
425 for i:= 0 to Targets.Count do |
561 for i:= 0 to Targets.Count do |
426 with Targets.ar[i] do |
562 if not Targets.ar[i].dead then |
427 begin |
563 with Targets.ar[i] do |
428 dmg:= 0; |
564 if not matters then hadSkips:= true |
429 if abs(Point.x - x) + abs(Point.y - y) < dmgBase then |
565 else |
430 dmg:= trunc(dmgMod * min((dmgBase - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)))) div 2, r)); |
566 begin |
431 |
567 dmg:= 0; |
432 if dmg > 0 then |
568 dmgBase:= r + Radius div 2; |
433 begin |
569 if abs(Point.x - x) + abs(Point.y - y) < dmgBase then |
434 if (Flags and afTrackFall <> 0) and (dmg < abs(Score)) then |
570 dmg:= trunc(dmgMod * min((dmgBase - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)))) div 2, r)); |
|
571 |
|
572 if dmg > 0 then |
435 begin |
573 begin |
436 dX:= 0.005 * dmg + 0.01; |
574 pX:= Point.x; |
437 dY:= dX; |
575 pY:= Point.y; |
438 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
576 fallDmg:= 0; |
439 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
577 dX:= 0; |
440 fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod) |
578 if (Flags and afTrackFall <> 0) and (Score > 0) and (dmg < Score) then |
441 else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod) |
579 begin |
442 end; |
580 dX:= (0.005 * dmg + 0.01) / Density; |
443 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
581 dY:= dX; |
444 if Score > 0 then |
582 if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and |
445 inc(rate, (KillScore + Score div 10) * 1024) // Add a bit of a bonus for bigger hog drownings |
583 (((abs(dY) >= 0.15) and (abs(dX) < 0.02)) or |
446 else |
584 ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then |
447 dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs |
585 dX:= 0; |
448 else if (dmg+fallDmg) >= abs(Score) then |
586 |
449 if Score > 0 then |
587 if pX - x < 0 then dX:= -dX; |
450 inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill |
588 if pY - y < 0 then dY:= -dY; |
451 else |
589 |
452 dec(rate, KillScore * friendlyfactor div 100 * 1024) |
590 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
453 else |
591 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
454 if Score > 0 then |
592 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod) |
455 inc(rate, (dmg + fallDmg) * 1024) |
593 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod) |
456 else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024) |
594 end; |
|
595 if Kind = gtHedgehog then |
|
596 begin |
|
597 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
|
598 begin |
|
599 if Score > 0 then |
|
600 inc(rate, (KillScore + Score div 10) * 1024) // Add a bit of a bonus for bigger hog drownings |
|
601 else |
|
602 dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs |
|
603 end |
|
604 else if (dmg+fallDmg) >= abs(Score) then |
|
605 begin |
|
606 dead:= true; |
|
607 Targets.reset:= true; |
|
608 if dX < 0.035 then |
|
609 begin |
|
610 subrate:= RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or (Flags and afTrackFall)); |
|
611 if abs(subrate) > 2000 then inc(Rate,subrate) |
|
612 end; |
|
613 if Score > 0 then |
|
614 inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill |
|
615 else dec(rate, KillScore * friendlyfactor div 100 * 1024) |
|
616 end |
|
617 else |
|
618 begin |
|
619 if Score > 0 then |
|
620 inc(rate, (dmg + fallDmg) * 1024) |
|
621 else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024) |
|
622 end |
|
623 end |
|
624 else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
|
625 begin |
|
626 dead:= true; |
|
627 Targets.reset:= true; |
|
628 if Kind = gtExplosives then |
|
629 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) |
|
630 else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall)); |
|
631 if abs(subrate) > 2000 then inc(Rate,subrate); |
|
632 end |
|
633 end |
457 end; |
634 end; |
458 end; |
635 |
459 RateExplosion:= rate; |
636 if hadSkips and (rate <= 0) then |
460 end; |
637 RealRateExplosion:= BadTurn |
461 |
638 else |
462 function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
639 RealRateExplosion:= rate; |
463 var i, fallDmg, dmg, rate: LongInt; |
640 end; |
464 dX, dY, dmgMod: real; |
641 |
|
642 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
|
643 var i, fallDmg, dmg, rate, subrate: LongInt; |
|
644 dX, dY, pX, pY: real; |
|
645 hadSkips: boolean; |
465 begin |
646 begin |
466 fallDmg:= 0; |
647 fallDmg:= 0; |
467 dX:= gdX * 0.01 * kick; |
648 dX:= gdX * 0.01 * kick; |
468 dY:= gdY * 0.01 * kick; |
649 dY:= gdY * 0.01 * kick; |
469 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; |
|
470 rate:= 0; |
650 rate:= 0; |
|
651 hadSkips:= false; |
471 for i:= 0 to Pred(Targets.Count) do |
652 for i:= 0 to Pred(Targets.Count) do |
472 with Targets.ar[i] do |
653 with Targets.ar[i] do |
473 if skip then |
654 if skip then |
474 if (Flags and afSetSkip = 0) then skip:= false else {still skip} |
655 begin |
475 else |
656 if Flags and afSetSkip = 0 then skip:= false |
476 begin |
657 end |
477 dmg:= 0; |
658 else if matters then |
478 if abs(Point.x - x) + abs(Point.y - y) < r then |
659 begin |
479 dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); |
660 dmg:= 0; |
480 |
661 if abs(Point.x - x) + abs(Point.y - y) < r then |
481 if dmg > 0 then |
662 dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); |
482 begin |
663 |
483 if (Flags and afSetSkip <> 0) then skip:= true; |
664 if dmg > 0 then |
484 if (Flags and afTrackFall <> 0) and (Score > 0) then |
665 begin |
485 fallDmg:= trunc(TraceShoveFall(Point.x, Point.y - 2, dX, dY) * dmgMod); |
666 pX:= Point.x; |
486 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
667 pY:= Point.y-2; |
487 if Score > 0 then |
668 fallDmg:= 0; |
488 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
669 if (Flags and afSetSkip <> 0) then skip:= true; |
489 else |
670 if (not dead) and (Flags and afTrackFall <> 0) and (Score > 0) and (power < Score) then |
490 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
671 if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and |
491 else if power+fallDmg >= abs(Score) then |
672 (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or |
492 if Score > 0 then |
673 ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then |
493 inc(rate, KillScore) |
674 fallDmg:= trunc(TraceShoveFall(pX, pY, 0, dY, Targets.ar[i]) * dmgMod) |
494 else |
675 else |
495 dec(rate, KillScore * friendlyfactor div 100) |
676 fallDmg:= trunc(TraceShoveFall(pX, pY, dX, dY, Targets.ar[i]) * dmgMod); |
496 else |
677 if Kind = gtHedgehog then |
497 if Score > 0 then |
678 begin |
498 inc(rate, power+fallDmg) |
679 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
499 else |
680 begin |
500 dec(rate, (power+fallDmg) * friendlyfactor div 100) |
681 if Score > 0 then |
501 end; |
682 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
502 end; |
683 else |
503 RateShove:= rate * 1024 |
684 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
|
685 end |
|
686 else if power+fallDmg >= abs(Score) then |
|
687 begin |
|
688 dead:= true; |
|
689 Targets.reset:= true; |
|
690 if dX < 0.035 then |
|
691 begin |
|
692 subrate:= RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall); |
|
693 if abs(subrate) > 2000 then inc(Rate,subrate div 1024) |
|
694 end; |
|
695 if Score > 0 then |
|
696 inc(rate, KillScore) |
|
697 else |
|
698 dec(rate, KillScore * friendlyfactor div 100) |
|
699 end |
|
700 else |
|
701 begin |
|
702 if Score > 0 then |
|
703 inc(rate, power+fallDmg) |
|
704 else |
|
705 dec(rate, (power+fallDmg) * friendlyfactor div 100) |
|
706 end |
|
707 end |
|
708 else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
|
709 begin |
|
710 dead:= true; |
|
711 Targets.reset:= true; |
|
712 if Kind = gtExplosives then |
|
713 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) |
|
714 else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall)); |
|
715 if abs(subrate) > 2000 then inc(Rate,subrate div 1024); |
|
716 end |
|
717 end |
|
718 end |
|
719 else |
|
720 hadSkips:= true; |
|
721 |
|
722 if hadSkips and (rate <= 0) then |
|
723 RateShove:= BadTurn |
|
724 else |
|
725 RateShove:= rate * 1024; |
|
726 ResetTargets |
504 end; |
727 end; |
505 |
728 |
506 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
729 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
507 var i, dmg, fallDmg, baseDmg, rate, erasure: LongInt; |
730 var i, dmg, fallDmg, baseDmg, rate, subrate, erasure: LongInt; |
508 dX, dY, dmgMod: real; |
731 pX, pY, dX, dY: real; |
509 begin |
732 hadSkips: boolean; |
510 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; |
733 begin |
511 rate:= 0; |
734 rate:= 0; |
512 gdX:= gdX * 0.01; |
735 gdX:= gdX * 0.01; |
513 gdY:= gdX * 0.01; |
736 gdY:= gdX * 0.01; |
514 // add our virtual position |
737 // add our virtual position |
515 with Targets.ar[Targets.Count] do |
738 with Targets.ar[Targets.Count] do |
516 begin |
739 begin |
517 Point.x:= hwRound(Me^.X); |
740 Point.x:= hwRound(Me^.X); |
518 Point.y:= hwRound(Me^.Y); |
741 Point.y:= hwRound(Me^.Y); |
|
742 skip:= false; |
|
743 matters:= true; |
|
744 Kind:= gtHedgehog; |
|
745 Density:= 1; |
|
746 Radius:= cHHRadius; |
519 Score:= - ThinkingHH^.Health |
747 Score:= - ThinkingHH^.Health |
520 end; |
748 end; |
521 // rate shot |
749 // rate shot |
522 baseDmg:= cHHRadius + cShotgunRadius + 4; |
750 baseDmg:= cHHRadius + cShotgunRadius + 4; |
|
751 |
523 if GameFlags and gfSolidLand = 0 then erasure:= cShotgunRadius |
752 if GameFlags and gfSolidLand = 0 then erasure:= cShotgunRadius |
524 else erasure:= 0; |
753 else erasure:= 0; |
|
754 |
|
755 hadSkips:= false; |
|
756 |
525 for i:= 0 to Targets.Count do |
757 for i:= 0 to Targets.Count do |
526 with Targets.ar[i] do |
758 if not Targets.ar[i].dead then |
527 begin |
759 with Targets.ar[i] do |
528 dmg:= 0; |
760 if not matters then hadSkips:= true |
529 if abs(Point.x - x) + abs(Point.y - y) < baseDmg then |
761 else |
530 begin |
762 begin |
531 dmg:= min(baseDmg - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))), 25); |
763 dmg:= 0; |
532 dmg:= trunc(dmg * dmgMod); |
764 if abs(Point.x - x) + abs(Point.y - y) < baseDmg then |
|
765 begin |
|
766 dmg:= min(baseDmg - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))), 25); |
|
767 dmg:= trunc(dmg * dmgMod); |
|
768 end; |
|
769 if dmg > 0 then |
|
770 begin |
|
771 fallDmg:= 0; |
|
772 pX:= Point.x; |
|
773 pY:= Point.y; |
|
774 if (not dead) and (Score > 0) and (dmg < Score) then |
|
775 begin |
|
776 dX:= gdX * dmg / Density; |
|
777 dY:= gdY * dmg / Density; |
|
778 if dX < 0 then dX:= dX - 0.01 |
|
779 else dX:= dX + 0.01; |
|
780 if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and |
|
781 (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or |
|
782 ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then |
|
783 dX:= 0; |
|
784 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
|
785 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
|
786 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod) |
|
787 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod) |
|
788 end; |
|
789 if Kind = gtHedgehog then |
|
790 begin |
|
791 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
|
792 begin |
|
793 if Score > 0 then |
|
794 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
|
795 else |
|
796 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
|
797 end |
|
798 else if (dmg+fallDmg) >= abs(Score) then |
|
799 begin |
|
800 dead:= true; |
|
801 Targets.reset:= true; |
|
802 if abs(gdX) < 0.035 then |
|
803 begin |
|
804 subrate:= RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall); |
|
805 if abs(subrate) > 2000 then inc(Rate,subrate div 1024) |
|
806 end; |
|
807 if Score > 0 then |
|
808 inc(rate, KillScore) |
|
809 else |
|
810 dec(rate, KillScore * friendlyfactor div 100) |
|
811 end |
|
812 else if Score > 0 then |
|
813 inc(rate, dmg+fallDmg) |
|
814 else dec(rate, (dmg+fallDmg) * friendlyfactor div 100) |
|
815 end |
|
816 else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
|
817 begin |
|
818 dead:= true; |
|
819 Targets.reset:= true; |
|
820 if Kind = gtExplosives then |
|
821 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or afTrackFall) |
|
822 else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or afTrackFall); |
|
823 if abs(subrate) > 2000 then inc(Rate,subrate div 1024); |
|
824 end |
|
825 end |
533 end; |
826 end; |
534 if dmg > 0 then |
827 |
535 begin |
828 if hadSkips and (rate <= 0) then |
536 dX:= gdX * dmg; |
829 RateShotgun:= BadTurn |
537 dY:= gdY * dmg; |
830 else |
538 if dX < 0 then dX:= dX - 0.01 |
831 RateShotgun:= rate * 1024; |
539 else dX:= dX + 0.01; |
832 ResetTargets; |
540 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
|
541 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
|
542 fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod) |
|
543 else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod); |
|
544 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
|
545 if Score > 0 then |
|
546 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
|
547 else |
|
548 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
|
549 else if (dmg+fallDmg) >= abs(Score) then |
|
550 if Score > 0 then |
|
551 inc(rate, KillScore) |
|
552 else |
|
553 dec(rate, KillScore * friendlyfactor div 100) |
|
554 else |
|
555 if Score > 0 then |
|
556 inc(rate, dmg+fallDmg) |
|
557 else |
|
558 dec(rate, (dmg+fallDmg) * friendlyfactor div 100) |
|
559 end; |
|
560 end; |
|
561 RateShotgun:= rate * 1024; |
|
562 end; |
833 end; |
563 |
834 |
564 function RateHammer(Me: PGear): LongInt; |
835 function RateHammer(Me: PGear): LongInt; |
565 var x, y, i, r, rate: LongInt; |
836 var x, y, i, r, rate: LongInt; |
|
837 hadSkips: boolean; |
566 begin |
838 begin |
567 // hammer hit shift against attecker hog is 10 |
839 // hammer hit shift against attecker hog is 10 |
568 x:= hwRound(Me^.X) + hwSign(Me^.dX) * 10; |
840 x:= hwRound(Me^.X) + hwSign(Me^.dX) * 10; |
569 y:= hwRound(Me^.Y); |
841 y:= hwRound(Me^.Y); |
570 rate:= 0; |
842 rate:= 0; |
571 |
843 hadSkips:= false; |
572 for i:= 0 to Pred(Targets.Count) do |
844 for i:= 0 to Pred(Targets.Count) do |
573 with Targets.ar[i] do |
845 with Targets.ar[i] do |
574 // hammer hit radius is 8, shift is 10 |
846 // hammer hit radius is 8, shift is 10 |
575 if abs(Point.x - x) + abs(Point.y - y) < 18 then |
847 if (not matters) then |
|
848 hadSkips:= true |
|
849 else if matters and (Kind = gtHedgehog) and (abs(Point.x - x) + abs(Point.y - y) < 18) then |
576 begin |
850 begin |
577 r:= trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); |
851 r:= trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); |
578 |
852 |
579 if r <= 18 then |
853 if r <= 18 then |
580 if Score > 0 then |
854 if Score > 0 then |
581 inc(rate, Score div 3) |
855 inc(rate, Score div 3) |
582 else |
856 else |
583 inc(rate, Score div 3 * friendlyfactor div 100) |
857 inc(rate, Score div 3 * friendlyfactor div 100) |
584 end; |
858 end; |
585 RateHammer:= rate * 1024; |
859 |
|
860 if hadSkips and (rate <= 0) then |
|
861 RateHammer:= BadTurn |
|
862 else |
|
863 RateHammer:= rate * 1024; |
586 end; |
864 end; |
587 |
865 |
588 function HHJump(Gear: PGear; JumpType: TJumpType; var GoInfo: TGoInfo): boolean; |
866 function HHJump(Gear: PGear; JumpType: TJumpType; var GoInfo: TGoInfo): boolean; |
589 var bX, bY: LongInt; |
867 var bX, bY: LongInt; |
590 begin |
868 begin |