53 |
57 |
54 procedure initModule; |
58 procedure initModule; |
55 procedure freeModule; |
59 procedure freeModule; |
56 |
60 |
57 procedure FillTargets; |
61 procedure FillTargets; |
|
62 procedure ResetTargets; inline; |
58 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline; |
63 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline; |
59 procedure FillBonuses(isAfterAttack: boolean); |
64 procedure FillBonuses(isAfterAttack: boolean); |
60 procedure AwareOfExplosion(x, y, r: LongInt); inline; |
65 procedure AwareOfExplosion(x, y, r: LongInt); inline; |
61 |
66 |
62 function RatePlace(Gear: PGear): LongInt; |
67 function RatePlace(Gear: PGear): LongInt; |
63 function TestColl(x, y, r: LongInt): boolean; inline; |
68 function TestColl(x, y, r: LongInt): boolean; inline; |
64 function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; |
69 function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; |
65 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; |
70 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; |
66 function TraceShoveFall(x, y, dX, dY: Real): LongInt; |
|
67 |
71 |
68 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; |
72 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; |
69 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
73 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline; |
70 function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
74 function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
|
75 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
71 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
76 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
72 function RateHammer(Me: PGear): LongInt; |
77 function RateHammer(Me: PGear): LongInt; |
73 |
78 |
74 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; |
79 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; |
75 function AIrndSign(num: LongInt): LongInt; |
80 function AIrndSign(num: LongInt): LongInt; |
97 var |
102 var |
98 KnownExplosion: record |
103 KnownExplosion: record |
99 X, Y, Radius: LongInt |
104 X, Y, Radius: LongInt |
100 end = (X: 0; Y: 0; Radius: 0); |
105 end = (X: 0; Y: 0; Radius: 0); |
101 |
106 |
|
107 procedure ResetTargets; inline; |
|
108 var i: LongWord; |
|
109 begin |
|
110 if Targets.reset then |
|
111 for i:= 0 to Targets.Count do |
|
112 Targets.ar[i].dead:= false; |
|
113 Targets.reset:= false; |
|
114 end; |
102 procedure FillTargets; |
115 procedure FillTargets; |
103 var i, t: Longword; |
116 var i, t: Longword; |
104 f, e: LongInt; |
117 f, e: LongInt; |
|
118 Gear: PGear; |
105 begin |
119 begin |
106 Targets.Count:= 0; |
120 Targets.Count:= 0; |
|
121 Targets.reset:= false; |
107 f:= 0; |
122 f:= 0; |
108 e:= 0; |
123 e:= 0; |
109 for t:= 0 to Pred(TeamsCount) do |
124 Gear:= GearsList; |
110 with TeamsArray[t]^ do |
125 while Gear <> nil do |
111 if not hasGone then |
126 begin |
112 begin |
127 if (((Gear^.Kind = gtHedgehog) and |
113 for i:= 0 to cMaxHHIndex do |
128 (Gear <> ThinkingHH) and |
114 if (Hedgehogs[i].Gear <> nil) |
129 (Gear^.Health > Gear^.Damage) and |
115 and (Hedgehogs[i].Gear <> ThinkingHH) |
130 not(Gear^.Hedgehog^.Team^.hasgone)) or |
116 and (Hedgehogs[i].Gear^.Health > Hedgehogs[i].Gear^.Damage) |
131 ((Gear^.Kind = gtExplosives) and |
117 then |
132 (Gear^.Health > Gear^.Damage)) or |
118 begin |
133 ((Gear^.Kind = gtMine) and |
119 with Targets.ar[Targets.Count], Hedgehogs[i] do |
134 (Gear^.Health = 0) and |
120 begin |
135 (Gear^.Damage < 35)) |
121 skip:= false; |
136 ) and |
122 matters:= (Hedgehogs[i].Gear^.AIHints and aihDoesntMatter) = 0; |
137 (Targets.Count < 256) then |
123 |
138 begin |
124 Point.X:= hwRound(Gear^.X); |
139 with Targets.ar[Targets.Count] do |
125 Point.Y:= hwRound(Gear^.Y); |
140 begin |
126 if Clan <> CurrentTeam^.Clan then |
141 skip:= false; |
127 begin |
142 dead:= false; |
128 Score:= Gear^.Health - Gear^.Damage; |
143 Kind:= Gear^.Kind; |
129 inc(e) |
144 Radius:= Gear^.Radius; |
130 end else |
145 Density:= hwFloat2Float(Gear^.Density)/3; |
131 begin |
146 State:= Gear^.State; |
132 Score:= Gear^.Damage - Gear^.Health; |
147 matters:= (Gear^.AIHints and aihDoesntMatter) = 0; |
133 inc(f) |
148 |
134 end |
149 Point.X:= hwRound(Gear^.X); |
135 end; |
150 Point.Y:= hwRound(Gear^.Y); |
136 inc(Targets.Count) |
151 if (Gear^.Kind = gtHedgehog) then |
|
152 begin |
|
153 if (Gear^.Hedgehog^.Team^.Clan = CurrentTeam^.Clan) then |
|
154 begin |
|
155 Score:= Gear^.Damage - Gear^.Health; |
|
156 inc(f) |
|
157 end |
|
158 else |
|
159 begin |
|
160 Score:= Gear^.Health - Gear^.Damage; |
|
161 inc(e) |
137 end; |
162 end; |
138 end; |
163 end |
|
164 else if Gear^.Kind = gtExplosives then |
|
165 Score:= Gear^.Health - Gear^.Damage |
|
166 else if Gear^.Kind = gtMine then |
|
167 Score:= max(0,35-Gear^.Damage); |
|
168 end; |
|
169 inc(Targets.Count) |
|
170 end; |
|
171 Gear:= Gear^.NextGear |
|
172 end; |
139 |
173 |
140 if e > f then friendlyfactor:= 300 + (e - f) * 30 |
174 if e > f then friendlyfactor:= 300 + (e - f) * 30 |
141 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e)) |
175 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e)) |
142 end; |
176 end; |
143 |
177 |
324 TestCollExcludingMe:= TestCollWithEverything(x, y, r) |
358 TestCollExcludingMe:= TestCollWithEverything(x, y, r) |
325 end; |
359 end; |
326 |
360 |
327 |
361 |
328 |
362 |
329 function TraceFall(eX, eY: LongInt; x, y, dX, dY: Real; r: LongWord): LongInt; |
363 function TraceFall(eX, eY: LongInt; var x, y: Real; dX, dY: Real; r: LongWord; Target: TTarget): LongInt; |
330 var skipLandCheck: boolean; |
364 var skipLandCheck: boolean; |
331 rCorner: real; |
365 rCorner, dxdy, odX, odY: real; |
332 dmg: LongInt; |
366 dmg: LongInt; |
333 begin |
367 begin |
|
368 odX:= dX; |
|
369 odY:= dY; |
334 skipLandCheck:= true; |
370 skipLandCheck:= true; |
335 if x - eX < 0 then dX:= -dX; |
|
336 if y - eY < 0 then dY:= -dY; |
|
337 // ok. attempt approximate search for an unbroken trajectory into water. if it continues far enough, assume out of map |
371 // ok. attempt approximate search for an unbroken trajectory into water. if it continues far enough, assume out of map |
338 rCorner:= r * 0.75; |
372 rCorner:= r * 0.75; |
339 while true do |
373 while true do |
340 begin |
374 begin |
341 x:= x + dX; |
375 x:= x + dX; |
342 y:= y + dY; |
376 y:= y + dY; |
343 dY:= dY + cGravityf; |
377 dY:= dY + cGravityf; |
344 skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner)); |
378 skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner)); |
345 if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), cHHRadius) then |
379 if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then |
346 begin |
380 with Target do |
347 if 0.4 < dY then |
381 begin |
348 begin |
382 if (Kind = gtHedgehog) and (0.4 < dY) then |
349 dmg := 1 + trunc((abs(dY) - 0.4) * 70); |
383 begin |
350 if dmg >= 1 then |
384 dmg := 1 + trunc((dY - 0.4) * 70); |
351 exit(dmg); |
385 exit(dmg) |
352 end; |
386 end |
|
387 else |
|
388 begin |
|
389 dxdy:= abs(dX)+abs(dY); |
|
390 if ((Kind = gtMine) and (dxdy > 0.35)) or |
|
391 ((Kind = gtExplosives) and |
|
392 (((State and gstTmpFlag <> 0) and (dxdy > 0.35)) or |
|
393 ((State and gstTmpFlag = 0) and |
|
394 ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and |
|
395 (abs(odX) > 0.02))) and (dxdy > 0.35)))) then |
|
396 begin |
|
397 dmg := trunc(dxdy * 25); |
|
398 exit(dmg) |
|
399 end |
|
400 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 |
|
401 begin |
|
402 dmg := trunc(dy * 70); |
|
403 exit(dmg) |
|
404 end |
|
405 end; |
353 exit(0) |
406 exit(0) |
354 end; |
407 end; |
355 if (y > cWaterLine) or (x > 4096) or (x < 0) then |
408 if (y > cWaterLine) or (x > rightX) or (x < leftX) then exit(-1) |
356 exit(-1); |
409 end |
357 end; |
410 end; |
358 end; |
411 |
359 |
412 function TraceShoveFall(var x, y: Real; dX, dY: Real; Target: TTarget): LongInt; |
360 function TraceShoveFall(x, y, dX, dY: Real): LongInt; |
|
361 var dmg: LongInt; |
413 var dmg: LongInt; |
362 begin |
414 dxdy, odX, odY: real; |
|
415 begin |
|
416 odX:= dX; |
|
417 odY:= dY; |
363 //v:= random($FFFFFFFF); |
418 //v:= random($FFFFFFFF); |
364 while true do |
419 while true do |
365 begin |
420 begin |
366 x:= x + dX; |
421 x:= x + dX; |
367 y:= y + dY; |
422 y:= y + dY; |
368 dY:= dY + cGravityf; |
423 dY:= dY + cGravityf; |
369 |
424 |
370 { if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then |
425 { if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then |
371 begin |
426 begin |
372 LandPixels[trunc(y), trunc(x)]:= v; |
427 LandPixels[trunc(y), trunc(x)]:= v; |
373 UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true); |
428 UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true); |
374 end;} |
429 end;} |
375 |
430 |
376 |
431 if TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then |
377 // consider adding dX/dY calc here for fall damage |
432 with Target do |
378 if TestCollExcludingObjects(trunc(x), trunc(y), cHHRadius) then |
433 begin |
379 begin |
434 if (Kind = gtHedgehog) and (0.4 < dY) then |
380 if 0.4 < dY then |
435 begin |
381 begin |
436 dmg := trunc((dY - 0.4) * 70); |
382 dmg := 1 + trunc((abs(dY) - 0.4) * 70); |
|
383 if dmg >= 1 then |
|
384 exit(dmg); |
437 exit(dmg); |
385 end; |
438 end |
|
439 else |
|
440 begin |
|
441 dxdy:= abs(dX)+abs(dY); |
|
442 if ((Kind = gtMine) and (dxdy > 0.4)) or |
|
443 ((Kind = gtExplosives) and |
|
444 (((State and gstTmpFlag <> 0) and (dxdy > 0.4)) or |
|
445 ((State and gstTmpFlag = 0) and |
|
446 ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and |
|
447 (abs(odX) > 0.02))) and (dxdy > 0.35)))) then |
|
448 begin |
|
449 dmg := trunc(dxdy * 50); |
|
450 exit(dmg) |
|
451 end |
|
452 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 |
|
453 begin |
|
454 dmg := trunc(dy * 70); |
|
455 exit(dmg) |
|
456 end |
|
457 end; |
386 exit(0) |
458 exit(0) |
387 end; |
459 end; |
388 if (y > cWaterLine) or (x > 4096) or (x < 0) then |
460 if (y > cWaterLine) or (x > rightX) or (x < leftX) then |
389 // returning -1 for drowning so it can be considered in the Rate routine |
461 // returning -1 for drowning so it can be considered in the Rate routine |
390 exit(-1) |
462 exit(-1) |
391 end; |
463 end; |
392 end; |
464 end; |
393 |
465 |
394 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; |
466 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; |
395 begin |
467 begin |
396 RateExplosion:= RateExplosion(Me, x, y, r, 0); |
468 RateExplosion:= RealRateExplosion(Me, x, y, r, 0); |
397 end; |
469 ResetTargets; |
398 |
470 end; |
399 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
471 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline; |
400 var i, fallDmg, dmg, dmgBase, rate, erasure: LongInt; |
472 begin |
401 dX, dY: real; |
473 RateExplosion:= RealRateExplosion(Me, x, y, r, Flags); |
|
474 ResetTargets; |
|
475 end; |
|
476 |
|
477 function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; |
|
478 var i, fallDmg, dmg, dmgBase, rate, subrate, erasure: LongInt; |
|
479 pX, pY, dX, dY: real; |
402 hadSkips: boolean; |
480 hadSkips: boolean; |
403 begin |
481 begin |
404 fallDmg:= 0; |
482 fallDmg:= 0; |
405 rate:= 0; |
483 rate:= 0; |
406 // add our virtual position |
484 // add our virtual position |
408 begin |
486 begin |
409 Point.x:= hwRound(Me^.X); |
487 Point.x:= hwRound(Me^.X); |
410 Point.y:= hwRound(Me^.Y); |
488 Point.y:= hwRound(Me^.Y); |
411 skip:= false; |
489 skip:= false; |
412 matters:= true; |
490 matters:= true; |
|
491 Kind:= gtHedgehog; |
|
492 Density:= 1; |
|
493 Radius:= cHHRadius; |
413 Score:= - ThinkingHH^.Health |
494 Score:= - ThinkingHH^.Health |
414 end; |
495 end; |
415 // rate explosion |
496 // rate explosion |
416 dmgBase:= r + cHHRadius div 2; |
|
417 |
497 |
418 if (Flags and afErasesLand <> 0) and (GameFlags and gfSolidLand = 0) then erasure:= r |
498 if (Flags and afErasesLand <> 0) and (GameFlags and gfSolidLand = 0) then erasure:= r |
419 else erasure:= 0; |
499 else erasure:= 0; |
420 |
500 |
421 hadSkips:= false; |
501 hadSkips:= false; |
422 |
502 |
423 for i:= 0 to Targets.Count do |
503 for i:= 0 to Targets.Count do |
424 with Targets.ar[i] do |
504 if not Targets.ar[i].dead then |
425 if not matters then hadSkips:= true |
505 with Targets.ar[i] do |
426 else |
506 if not matters then hadSkips:= true |
427 begin |
507 else |
428 dmg:= 0; |
508 begin |
429 if abs(Point.x - x) + abs(Point.y - y) < dmgBase then |
509 dmg:= 0; |
430 dmg:= trunc(dmgMod * min((dmgBase - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)))) div 2, r)); |
510 dmgBase:= r + Radius div 2; |
431 |
511 if abs(Point.x - x) + abs(Point.y - y) < dmgBase then |
432 if dmg > 0 then |
512 dmg:= trunc(dmgMod * min((dmgBase - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)))) div 2, r)); |
433 begin |
513 |
434 if (Flags and afTrackFall <> 0) and (dmg < abs(Score)) then |
514 if dmg > 0 then |
435 begin |
515 begin |
436 dX:= 0.005 * dmg + 0.01; |
516 pX:= Point.x; |
437 dY:= dX; |
517 pY:= Point.y; |
438 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
518 fallDmg:= 0; |
439 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
519 if (Flags and afTrackFall <> 0) and (Score > 0) and (dmg < Score) then |
440 fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod) |
520 begin |
441 else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod) |
521 dX:= (0.005 * dmg + 0.01) / Density; |
442 end; |
522 dY:= dX; |
443 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
523 if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and |
444 if Score > 0 then |
524 (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or |
445 inc(rate, (KillScore + Score div 10) * 1024) // Add a bit of a bonus for bigger hog drownings |
525 ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then |
446 else |
526 dX:= 0; |
447 dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs |
527 |
448 else if (dmg+fallDmg) >= abs(Score) then |
528 if pX - x < 0 then dX:= -dX; |
449 if Score > 0 then |
529 if pY - y < 0 then dY:= -dY; |
450 inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill |
530 |
451 else |
531 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
452 dec(rate, KillScore * friendlyfactor div 100 * 1024) |
532 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
453 else |
533 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod) |
454 if Score > 0 then |
534 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod) |
455 inc(rate, (dmg + fallDmg) * 1024) |
535 end; |
456 else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024) |
536 if Kind = gtHedgehog then |
457 end; |
537 begin |
458 end; |
538 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
|
539 begin |
|
540 if Score > 0 then |
|
541 inc(rate, (KillScore + Score div 10) * 1024) // Add a bit of a bonus for bigger hog drownings |
|
542 else |
|
543 dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs |
|
544 end |
|
545 else if (dmg+fallDmg) >= abs(Score) then |
|
546 begin |
|
547 dead:= true; |
|
548 Targets.reset:= true; |
|
549 if dX < 0.035 then |
|
550 begin |
|
551 subrate:= RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or (Flags and afTrackFall)); |
|
552 if abs(subrate) > 2000 then inc(Rate,subrate) |
|
553 end; |
|
554 if Score > 0 then |
|
555 inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill |
|
556 else dec(rate, KillScore * friendlyfactor div 100 * 1024) |
|
557 end |
|
558 else |
|
559 begin |
|
560 if Score > 0 then |
|
561 inc(rate, (dmg + fallDmg) * 1024) |
|
562 else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024) |
|
563 end |
|
564 end |
|
565 else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
|
566 begin |
|
567 dead:= true; |
|
568 Targets.reset:= true; |
|
569 if Kind = gtExplosives then |
|
570 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) |
|
571 else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall)); |
|
572 if abs(subrate) > 2000 then inc(Rate,subrate); |
|
573 end |
|
574 end |
|
575 end; |
459 |
576 |
460 if hadSkips and (rate = 0) then |
577 if hadSkips and (rate = 0) then |
461 RateExplosion:= BadTurn |
578 RealRateExplosion:= BadTurn |
462 else |
579 else |
463 RateExplosion:= rate; |
580 RealRateExplosion:= rate; |
464 end; |
581 end; |
465 |
582 |
466 function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
583 function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; |
467 var i, fallDmg, dmg, rate: LongInt; |
584 var i, fallDmg, dmg, rate, subrate: LongInt; |
468 dX, dY: real; |
585 dX, dY, pX, pY: real; |
469 begin |
586 begin |
470 fallDmg:= 0; |
587 fallDmg:= 0; |
471 dX:= gdX * 0.01 * kick; |
588 dX:= gdX * 0.01 * kick; |
472 dY:= gdY * 0.01 * kick; |
589 dY:= gdY * 0.01 * kick; |
473 rate:= 0; |
590 rate:= 0; |
474 for i:= 0 to Pred(Targets.Count) do |
591 for i:= 0 to Pred(Targets.Count) do |
475 with Targets.ar[i] do |
592 with Targets.ar[i] do |
476 if skip then |
593 if skip then |
477 if (Flags and afSetSkip = 0) then skip:= false else {still skip} |
594 begin |
478 else if matters then |
595 if Flags and afSetSkip = 0 then skip:= false |
479 begin |
596 end |
480 dmg:= 0; |
597 else if matters then |
481 if abs(Point.x - x) + abs(Point.y - y) < r then |
598 begin |
482 dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); |
599 dmg:= 0; |
483 |
600 if abs(Point.x - x) + abs(Point.y - y) < r then |
484 if dmg > 0 then |
601 dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); |
485 begin |
602 |
486 if (Flags and afSetSkip <> 0) then skip:= true; |
603 if dmg > 0 then |
487 if (Flags and afTrackFall <> 0) and (Score > 0) then |
604 begin |
488 fallDmg:= trunc(TraceShoveFall(Point.x, Point.y - 2, dX, dY) * dmgMod); |
605 pX:= Point.x; |
489 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
606 pY:= Point.y-2; |
490 if Score > 0 then |
607 fallDmg:= 0; |
491 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
608 if (Flags and afSetSkip <> 0) then skip:= true; |
492 else |
609 if not(dead) and (Flags and afTrackFall <> 0) and (Score > 0) and (power < Score) then |
493 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
610 if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and |
494 else if power+fallDmg >= abs(Score) then |
611 (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or |
495 if Score > 0 then |
612 ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then |
496 inc(rate, KillScore) |
613 fallDmg:= trunc(TraceShoveFall(pX, pY, 0, dY, Targets.ar[i]) * dmgMod) |
497 else |
614 else |
498 dec(rate, KillScore * friendlyfactor div 100) |
615 fallDmg:= trunc(TraceShoveFall(pX, pY, dX, dY, Targets.ar[i]) * dmgMod); |
499 else |
616 if Kind = gtHedgehog then |
500 if Score > 0 then |
617 begin |
501 inc(rate, power+fallDmg) |
618 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
502 else |
619 begin |
503 dec(rate, (power+fallDmg) * friendlyfactor div 100) |
620 if Score > 0 then |
504 end; |
621 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
505 end; |
622 else |
506 RateShove:= rate * 1024 |
623 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
|
624 end |
|
625 else if power+fallDmg >= abs(Score) then |
|
626 begin |
|
627 dead:= true; |
|
628 Targets.reset:= true; |
|
629 if dX < 0.035 then |
|
630 begin |
|
631 subrate:= RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall); |
|
632 if abs(subrate) > 2000 then inc(Rate,subrate div 1024) |
|
633 end; |
|
634 if Score > 0 then |
|
635 inc(rate, KillScore) |
|
636 else |
|
637 dec(rate, KillScore * friendlyfactor div 100) |
|
638 end |
|
639 else |
|
640 begin |
|
641 if Score > 0 then |
|
642 inc(rate, power+fallDmg) |
|
643 else |
|
644 dec(rate, (power+fallDmg) * friendlyfactor div 100) |
|
645 end |
|
646 end |
|
647 else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
|
648 begin |
|
649 dead:= true; |
|
650 Targets.reset:= true; |
|
651 if Kind = gtExplosives then |
|
652 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall)) |
|
653 else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall)); |
|
654 if abs(subrate) > 2000 then inc(Rate,subrate div 1024); |
|
655 end |
|
656 end |
|
657 end; |
|
658 RateShove:= rate * 1024; |
|
659 ResetTargets |
507 end; |
660 end; |
508 |
661 |
509 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
662 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; |
510 var i, dmg, fallDmg, baseDmg, rate, erasure: LongInt; |
663 var i, dmg, fallDmg, baseDmg, rate, subrate, erasure: LongInt; |
511 dX, dY: real; |
664 pX, pY, dX, dY: real; |
512 hadSkips: boolean; |
665 hadSkips: boolean; |
513 begin |
666 begin |
514 rate:= 0; |
667 rate:= 0; |
515 gdX:= gdX * 0.01; |
668 gdX:= gdX * 0.01; |
516 gdY:= gdX * 0.01; |
669 gdY:= gdX * 0.01; |
530 else erasure:= 0; |
686 else erasure:= 0; |
531 |
687 |
532 hadSkips:= false; |
688 hadSkips:= false; |
533 |
689 |
534 for i:= 0 to Targets.Count do |
690 for i:= 0 to Targets.Count do |
535 with Targets.ar[i] do |
691 if not Targets.ar[i].dead then |
536 if not matters then hadSkips:= true |
692 with Targets.ar[i] do |
537 else |
693 if not matters then hadSkips:= true |
538 begin |
|
539 dmg:= 0; |
|
540 if abs(Point.x - x) + abs(Point.y - y) < baseDmg then |
|
541 begin |
|
542 dmg:= min(baseDmg - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))), 25); |
|
543 dmg:= trunc(dmg * dmgMod); |
|
544 end; |
|
545 if dmg > 0 then |
|
546 begin |
|
547 dX:= gdX * dmg; |
|
548 dY:= gdY * dmg; |
|
549 if dX < 0 then dX:= dX - 0.01 |
|
550 else dX:= dX + 0.01; |
|
551 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
|
552 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
|
553 fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod) |
|
554 else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod); |
|
555 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
|
556 if Score > 0 then |
|
557 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
|
558 else |
|
559 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
|
560 else if (dmg+fallDmg) >= abs(Score) then |
|
561 if Score > 0 then |
|
562 inc(rate, KillScore) |
|
563 else |
|
564 dec(rate, KillScore * friendlyfactor div 100) |
|
565 else |
694 else |
566 if Score > 0 then |
695 begin |
567 inc(rate, dmg+fallDmg) |
696 dmg:= 0; |
568 else |
697 if abs(Point.x - x) + abs(Point.y - y) < baseDmg then |
569 dec(rate, (dmg+fallDmg) * friendlyfactor div 100) |
698 begin |
570 end; |
699 dmg:= min(baseDmg - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))), 25); |
571 end; |
700 dmg:= trunc(dmg * dmgMod); |
|
701 end; |
|
702 if dmg > 0 then |
|
703 begin |
|
704 if not(dead) and (Score > 0) and (dmg < Score) then |
|
705 begin |
|
706 pX:= Point.x; |
|
707 pY:= Point.y; |
|
708 dX:= gdX * dmg / Density; |
|
709 dY:= gdY * dmg / Density; |
|
710 if dX < 0 then dX:= dX - 0.01 |
|
711 else dX:= dX + 0.01; |
|
712 if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and |
|
713 (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or |
|
714 ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then |
|
715 dX:= 0; |
|
716 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and |
|
717 (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then |
|
718 fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod) |
|
719 else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod) |
|
720 end; |
|
721 if Kind = gtHedgehog then |
|
722 begin |
|
723 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI |
|
724 begin |
|
725 if Score > 0 then |
|
726 inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings |
|
727 else |
|
728 dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs |
|
729 end |
|
730 else if (dmg+fallDmg) >= abs(Score) then |
|
731 begin |
|
732 dead:= true; |
|
733 Targets.reset:= true; |
|
734 if dX < 0.035 then |
|
735 begin |
|
736 subrate:= RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall); |
|
737 if abs(subrate) > 2000 then inc(Rate,subrate div 1024) |
|
738 end; |
|
739 if Score > 0 then |
|
740 inc(rate, KillScore) |
|
741 else |
|
742 dec(rate, KillScore * friendlyfactor div 100) |
|
743 end |
|
744 else if Score > 0 then |
|
745 inc(rate, dmg+fallDmg) |
|
746 else dec(rate, (dmg+fallDmg) * friendlyfactor div 100) |
|
747 end |
|
748 else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then |
|
749 begin |
|
750 dead:= true; |
|
751 Targets.reset:= true; |
|
752 if Kind = gtExplosives then |
|
753 subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or afTrackFall) |
|
754 else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or afTrackFall); |
|
755 if abs(subrate) > 2000 then inc(Rate,subrate div 1024); |
|
756 end |
|
757 end |
|
758 end; |
572 |
759 |
573 if hadSkips and (rate = 0) then |
760 if hadSkips and (rate = 0) then |
574 RateShotgun:= BadTurn |
761 RateShotgun:= BadTurn |
575 else |
762 else |
576 RateShotgun:= rate * 1024; |
763 RateShotgun:= rate * 1024; |
|
764 ResetTargets; |
577 end; |
765 end; |
578 |
766 |
579 function RateHammer(Me: PGear): LongInt; |
767 function RateHammer(Me: PGear): LongInt; |
580 var x, y, i, r, rate: LongInt; |
768 var x, y, i, r, rate: LongInt; |
581 begin |
769 begin |