1 (* |
1 (* |
2 * Hedgewars, a free turn based strategy game |
2 * Hedgewars, a free turn based strategy game |
3 * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com> |
3 * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com> |
4 * |
4 * |
5 * This program is free software; you can redistribute it and/or modify |
5 * This program is free software; you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License as published by |
6 * it under the terms of the GNU General Public License as published by |
7 * the Free Software Foundation; version 2 of the License |
7 * the Free Software Foundation; version 2 of the License |
8 * |
8 * |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. |
12 * GNU General Public License for more details. |
13 * |
13 * |
14 * You should have received a copy of the GNU General Public License |
14 * You should have received a copy of the GNU General Public License |
15 * along with this program; if not, write to the Free Software |
15 * along with this program; if not, write to the Free Software |
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 *) |
17 *) |
18 |
18 |
19 {$INCLUDE "options.inc"} |
19 {$INCLUDE "options.inc"} |
20 |
20 |
21 unit uAI; |
21 unit uAI; |
106 procedure TestAmmos(var Actions: TActions; Me: PGear; rareChecks: boolean); |
106 procedure TestAmmos(var Actions: TActions; Me: PGear; rareChecks: boolean); |
107 var BotLevel: Byte; |
107 var BotLevel: Byte; |
108 ap: TAttackParams; |
108 ap: TAttackParams; |
109 Score, i, t, n, dAngle: LongInt; |
109 Score, i, t, n, dAngle: LongInt; |
110 a, aa: TAmmoType; |
110 a, aa: TAmmoType; |
|
111 useThisActions: boolean; |
111 begin |
112 begin |
112 BotLevel:= Me^.Hedgehog^.BotLevel; |
113 BotLevel:= Me^.Hedgehog^.BotLevel; |
113 windSpeed:= hwFloat2Float(cWindSpeed); |
114 windSpeed:= hwFloat2Float(cWindSpeed); |
|
115 useThisActions:= false; |
114 |
116 |
115 for i:= 0 to Pred(Targets.Count) do |
117 for i:= 0 to Pred(Targets.Count) do |
116 if (Targets.ar[i].Score >= 0) and (not StopThinking) then |
118 if (Targets.ar[i].Score >= 0) and (not StopThinking) then |
117 begin |
119 begin |
118 with Me^.Hedgehog^ do |
120 with Me^.Hedgehog^ do |
126 then |
128 then |
127 begin |
129 begin |
128 {$HINTS OFF} |
130 {$HINTS OFF} |
129 Score:= AmmoTests[a].proc(Me, Targets.ar[i], BotLevel, ap); |
131 Score:= AmmoTests[a].proc(Me, Targets.ar[i], BotLevel, ap); |
130 {$HINTS ON} |
132 {$HINTS ON} |
131 if Actions.Score + Score > BestActions.Score then |
133 if (Score > BadTurn) and (Actions.Score + Score > BestActions.Score) then |
132 if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + Byte(BotLevel - 1) * 2048) then |
134 if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + Byte(BotLevel - 1) * 2048) then |
133 begin |
135 begin |
134 BestActions:= Actions; |
136 if useThisActions then |
135 inc(BestActions.Score, Score); |
137 begin |
136 BestActions.isWalkingToABetterPlace:= false; |
138 BestActions.Count:= Actions.Count |
|
139 end |
|
140 else |
|
141 begin |
|
142 BestActions:= Actions; |
|
143 BestActions.isWalkingToABetterPlace:= false; |
|
144 useThisActions:= true |
|
145 end; |
|
146 |
|
147 BestActions.Score:= Actions.Score + Score; |
|
148 |
|
149 // if not between shots, activate invulnerability/vampirism if available |
|
150 if CurrentHedgehog^.MultiShootAttacks = 0 then |
|
151 begin |
|
152 if HHHasAmmo(Me^.Hedgehog^, amInvulnerable) > 0 then |
|
153 begin |
|
154 AddAction(BestActions, aia_Weapon, Longword(amInvulnerable), 80, 0, 0); |
|
155 AddAction(BestActions, aia_attack, aim_push, 10, 0, 0); |
|
156 AddAction(BestActions, aia_attack, aim_release, 10, 0, 0); |
|
157 end; |
|
158 |
|
159 if HHHasAmmo(Me^.Hedgehog^, amExtraDamage) > 0 then |
|
160 begin |
|
161 AddAction(BestActions, aia_Weapon, Longword(amExtraDamage), 80, 0, 0); |
|
162 AddAction(BestActions, aia_attack, aim_push, 10, 0, 0); |
|
163 AddAction(BestActions, aia_attack, aim_release, 10, 0, 0); |
|
164 end; |
|
165 end; |
137 |
166 |
138 AddAction(BestActions, aia_Weapon, Longword(a), 300 + random(400), 0, 0); |
167 AddAction(BestActions, aia_Weapon, Longword(a), 300 + random(400), 0, 0); |
139 |
168 |
140 if (ap.Angle > 0) then |
169 if (ap.Angle > 0) then |
141 AddAction(BestActions, aia_LookRight, 0, 200, 0, 0) |
170 AddAction(BestActions, aia_LookRight, 0, 200, 0, 0) |
249 // switch to 'skip' if we cannot move because of mouse cursor being shown |
278 // switch to 'skip' if we cannot move because of mouse cursor being shown |
250 if (Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then |
279 if (Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then |
251 AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0); |
280 AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0); |
252 |
281 |
253 if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0)) |
282 if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0)) |
254 and (GameFlags and gfArtillery = 0) then |
283 and (GameFlags and gfArtillery = 0) and (cGravityf <> 0) then |
255 begin |
284 begin |
256 tmp:= random(2) + 1; |
285 tmp:= random(2) + 1; |
257 Push(0, Actions, Me^, tmp); |
286 Push(0, Actions, Me^, tmp); |
258 Push(0, Actions, Me^, tmp xor 3); |
287 Push(0, Actions, Me^, tmp xor 3); |
259 |
288 |
368 end; |
401 end; |
369 |
402 |
370 function Think(Me: PGear): LongInt; cdecl; export; |
403 function Think(Me: PGear): LongInt; cdecl; export; |
371 var BackMe, WalkMe: TGear; |
404 var BackMe, WalkMe: TGear; |
372 switchCount: LongInt; |
405 switchCount: LongInt; |
373 StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i: Longword; |
406 currHedgehogIndex, itHedgehog, switchesNum, i: Longword; |
374 switchImmediatelyAvailable: boolean; |
407 switchImmediatelyAvailable: boolean; |
375 Actions: TActions; |
408 Actions: TActions; |
376 begin |
409 begin |
377 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; |
410 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; |
378 StartTicks:= GameTicks; |
411 StartTicks:= GameTicks; |
|
412 |
379 currHedgehogIndex:= CurrentTeam^.CurrHedgehog; |
413 currHedgehogIndex:= CurrentTeam^.CurrHedgehog; |
380 itHedgehog:= currHedgehogIndex; |
414 itHedgehog:= currHedgehogIndex; |
381 switchesNum:= 0; |
415 switchesNum:= 0; |
382 |
416 |
383 switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher); |
417 switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher); |
384 if Me^.Hedgehog^.BotLevel <> 5 then |
418 if Me^.Hedgehog^.BotLevel <> 5 then |
385 switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch) |
419 switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch) |
386 else switchCount:= 0; |
420 else switchCount:= 0; |
387 |
421 |
388 if ((Me^.State and gstAttacked) = 0) or isInMultiShoot then |
422 if ((Me^.State and gstAttacked) = 0) or isInMultiShoot or bonuses.activity then |
389 if Targets.Count > 0 then |
423 if Targets.Count > 0 then |
390 begin |
424 begin |
391 // iterate over current team hedgehogs |
425 // iterate over current team hedgehogs |
392 repeat |
426 repeat |
393 WalkMe:= CurrentTeam^.Hedgehogs[itHedgehog].Gear^; |
427 WalkMe:= CurrentTeam^.Hedgehogs[itHedgehog].Gear^; |
395 Actions.Count:= 0; |
429 Actions.Count:= 0; |
396 Actions.Pos:= 0; |
430 Actions.Pos:= 0; |
397 Actions.Score:= 0; |
431 Actions.Score:= 0; |
398 if switchesNum > 0 then |
432 if switchesNum > 0 then |
399 begin |
433 begin |
400 if not switchImmediatelyAvailable then |
434 if (not switchImmediatelyAvailable) then |
401 begin |
435 begin |
402 // when AI has to use switcher, make it cost smth unless they have a lot of switches |
436 // when AI has to use switcher, make it cost smth unless they have a lot of switches |
403 if (switchCount < 10) then Actions.Score:= (-27+switchCount*3)*4000; |
437 if (switchCount < 10) then Actions.Score:= (-27+switchCount*3)*4000; |
404 AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0); |
438 AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0); |
405 AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0); |
439 AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0); |
419 until (not (switchImmediatelyAvailable or (switchCount > 0))) |
453 until (not (switchImmediatelyAvailable or (switchCount > 0))) |
420 or StopThinking |
454 or StopThinking |
421 or (itHedgehog = currHedgehogIndex) |
455 or (itHedgehog = currHedgehogIndex) |
422 or BestActions.isWalkingToABetterPlace; |
456 or BestActions.isWalkingToABetterPlace; |
423 |
457 |
424 if (StartTicks > GameTicks - 1500) and (not StopThinking) then |
458 if (StartTicks > GameTicks - 1500) and (not StopThinking) then |
425 SDL_Delay(1000); |
459 SDL_Delay(700); |
426 |
460 |
427 if (BestActions.Score < -1023) and (not BestActions.isWalkingToABetterPlace) then |
461 if (BestActions.Score < -1023) and (not BestActions.isWalkingToABetterPlace) then |
428 begin |
462 begin |
429 BestActions.Count:= 0; |
463 BestActions.Count:= 0; |
430 AddAction(BestActions, aia_Skip, 0, 250, 0, 0); |
464 |
|
465 FillBonuses(false); |
|
466 |
|
467 if not bonuses.activity then |
|
468 AddAction(BestActions, aia_Skip, 0, 250, 0, 0); |
431 end; |
469 end; |
432 |
470 |
433 end else SDL_Delay(100) |
471 end else SDL_Delay(100) |
434 else |
472 else |
435 begin |
473 begin |
436 BackMe:= Me^; |
474 BackMe:= Me^; |
437 i:= 12; |
475 i:= 4; |
438 while (not StopThinking) and (BestActions.Count = 0) and (i > 0) do |
476 while (not StopThinking) and (BestActions.Count = 0) and (i > 0) do |
439 begin |
477 begin |
|
478 |
440 (* |
479 (* |
441 // Maybe this would get a bit of movement out of them? Hopefully not *toward* water. Need to check how often he'd choose that strategy |
480 // Maybe this would get a bit of movement out of them? Hopefully not *toward* water. Need to check how often he'd choose that strategy |
442 if SuddenDeathDmg and ((hwRound(BackMe.Y)+cWaterRise*2) > cWaterLine) then |
481 if SuddenDeathDmg and ((hwRound(BackMe.Y)+cWaterRise*2) > cWaterLine) then |
443 AddBonus(hwRound(BackMe.X), hwRound(BackMe.Y), 250, -40); |
482 AddBonus(hwRound(BackMe.X), hwRound(BackMe.Y), 250, -40); |
444 *) |
483 *) |
|
484 |
445 FillBonuses(true); |
485 FillBonuses(true); |
446 WalkMe:= BackMe; |
486 WalkMe:= BackMe; |
447 Actions.Count:= 0; |
487 Actions.Count:= 0; |
448 Actions.Pos:= 0; |
488 Actions.Pos:= 0; |
449 Actions.Score:= 0; |
489 Actions.Score:= 0; |
450 Walk(@WalkMe, Actions); |
490 Walk(@WalkMe, Actions); |
451 dec(i); |
491 if not bonuses.activity then dec(i); |
452 if not StopThinking then |
492 if not StopThinking then |
453 SDL_Delay(100) |
493 SDL_Delay(100) |
454 end |
494 end |
455 end; |
495 end; |
456 |
496 |