--- a/hedgewars/uAI.pas Mon Jan 16 10:22:21 2012 +0100
+++ b/hedgewars/uAI.pas Tue Jan 17 09:01:31 2012 -0500
@@ -30,8 +30,8 @@
implementation
uses uConsts, SDLh, uAIMisc, uAIAmmoTests, uAIActions,
- uAmmos, SysUtils{$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF}, uTypes,
- uVariables, uCommands, uUtils, uDebug;
+ uAmmos, SysUtils{$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF}, uTypes,
+ uVariables, uCommands, uUtils, uDebug;
var BestActions: TActions;
CanUseAmmo: array [TAmmoType] of boolean;
@@ -47,18 +47,18 @@
begin
AddFileLog('FreeActionsList called');
if hasThread <> 0 then
- begin
- AddFileLog('Waiting AI thread to finish');
- StopThinking:= true;
- repeat
- SDL_Delay(10)
- until hasThread = 0
- end;
+ begin
+ AddFileLog('Waiting AI thread to finish');
+ StopThinking:= true;
+ repeat
+ SDL_Delay(10)
+ until hasThread = 0
+ end;
with CurrentHedgehog^ do
- if Gear <> nil then
+ if Gear <> nil then
if BotLevel <> 0 then
- StopMessages(Gear^.Message);
+ StopMessages(Gear^.Message);
BestActions.Count:= 0;
BestActions.Pos:= 0
@@ -117,66 +117,71 @@
for i:= 0 to Pred(Targets.Count) do
if (Targets.ar[i].Score >= 0) and (not StopThinking) then
- begin
- with CurrentHedgehog^ do
+ begin
+ with CurrentHedgehog^ do
a:= CurAmmoType;
- aa:= a;
+ aa:= a;
{$IFDEF USE_SDLTHREADS}
- SDL_delay(0); //ThreadSwitch was only a hint
+ SDL_delay(0); //ThreadSwitch was only a hint
{$ELSE}
- ThreadSwitch();
+ ThreadSwitch();
{$ENDIF}
- repeat
+ repeat
if (CanUseAmmo[a]) and
- ((not isMoved) or ((AmmoTests[a].flags and amtest_OnTurn) = 0)) then
- begin
+ ((not isMoved) or ((AmmoTests[a].flags and amtest_OnTurn) = 0)) then
+ begin
{$HINTS OFF}
- Score:= AmmoTests[a].proc(Me, Targets.ar[i].Point, BotLevel, ap);
+ Score:= AmmoTests[a].proc(Me, Targets.ar[i].Point, BotLevel, ap);
{$HINTS ON}
- if Actions.Score + Score > BestActions.Score then
- if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + Byte(BotLevel) * 2048) then
- begin
- BestActions:= Actions;
- inc(BestActions.Score, Score);
- BestActions.isWalkingToABetterPlace:= false;
+ if Actions.Score + Score > BestActions.Score then
+ if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + Byte(BotLevel) * 2048) then
+ begin
+ BestActions:= Actions;
+ inc(BestActions.Score, Score);
+ BestActions.isWalkingToABetterPlace:= false;
- if (ap.Angle > 0) then AddAction(BestActions, aia_LookRight, 0, 200, 0, 0)
- else if (ap.Angle < 0) then AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0);
+ if (ap.Angle > 0) then
+ AddAction(BestActions, aia_LookRight, 0, 200, 0, 0)
+ else if (ap.Angle < 0) then
+ AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0);
- AddAction(BestActions, aia_Weapon, Longword(a), 300 + random(400), 0, 0);
- if (ap.Time <> 0) then AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0);
- if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then
- begin
- ap.Angle:= LongInt(Me^.Angle) - Abs(ap.Angle);
- if ap.Angle > 0 then
- begin
- AddAction(BestActions, aia_Up, aim_push, 300 + random(250), 0, 0);
- AddAction(BestActions, aia_Up, aim_release, ap.Angle, 0, 0)
- end else if ap.Angle < 0 then
+ AddAction(BestActions, aia_Weapon, Longword(a), 300 + random(400), 0, 0);
+
+ if (ap.Time <> 0) then
+ AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0);
+ if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then
begin
- AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0);
- AddAction(BestActions, aia_Down, aim_release, -ap.Angle, 0, 0)
- end
- end;
- if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
- begin
- AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY)
- end;
- if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then
- begin
- AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0);
- AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0);
- end;
- if ap.ExplR > 0 then
- AddAction(BestActions, aia_AwareExpl, ap.ExplR, 10, ap.ExplX, ap.ExplY);
- end
- end;
- if a = High(TAmmoType) then a:= Low(TAmmoType)
- else inc(a)
- until (a = aa) or
- (CurrentHedgehog^.MultiShootAttacks > 0) or // shooting same weapon
- StopThinking
- end
+ ap.Angle:= LongInt(Me^.Angle) - Abs(ap.Angle);
+ if ap.Angle > 0 then
+ begin
+ AddAction(BestActions, aia_Up, aim_push, 300 + random(250), 0, 0);
+ AddAction(BestActions, aia_Up, aim_release, ap.Angle, 0, 0)
+ end
+ else if ap.Angle < 0 then
+ begin
+ AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0);
+ AddAction(BestActions, aia_Down, aim_release, -ap.Angle, 0, 0)
+ end
+ end;
+ if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
+ begin
+ AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY)
+ end;
+ if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then
+ begin
+ AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0);
+ AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0);
+ end;
+ if ap.ExplR > 0 then
+ AddAction(BestActions, aia_AwareExpl, ap.ExplR, 10, ap.ExplX, ap.ExplY);
+ end
+ end;
+ if a = High(TAmmoType) then
+ a:= Low(TAmmoType)
+ else inc(a)
+ until (a = aa) or (CurrentHedgehog^.MultiShootAttacks > 0) or // shooting same weapon
+ StopThinking
+ end
end;
procedure Walk(Me: PGear; var Actions: TActions);
@@ -202,10 +207,14 @@
Push(0, Actions, Me^, tmp);
Push(0, Actions, Me^, tmp xor 3);
-if (Me^.State and gstAttacked) = 0 then maxticks:= Max(0, TurnTimeLeft - 5000 - LongWord(4000 * BotLevel))
- else maxticks:= TurnTimeLeft;
+if (Me^.State and gstAttacked) = 0 then
+ maxticks:= Max(0, TurnTimeLeft - 5000 - LongWord(4000 * BotLevel))
+else
+ maxticks:= TurnTimeLeft;
-if (Me^.State and gstAttacked) = 0 then TestAmmos(Actions, Me, false);
+if (Me^.State and gstAttacked) = 0 then
+ TestAmmos(Actions, Me, false);
+
BestRate:= RatePlace(Me);
BaseRate:= Max(BestRate, 0);
@@ -217,54 +226,67 @@
Pop(ticks, Actions, Me^);
AddAction(Actions, Me^.Message, aim_push, 250, 0, 0);
- if (Me^.Message and gmLeft) <> 0 then AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
- else AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0);
+ if (Me^.Message and gmLeft) <> 0 then
+ AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
+ else
+ AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0);
+
steps:= 0;
while (not StopThinking) do
- begin
+ begin
{$HINTS OFF}
- CanGo:= HHGo(Me, @AltMe, GoInfo);
+ CanGo:= HHGo(Me, @AltMe, GoInfo);
{$HINTS ON}
- inc(ticks, GoInfo.Ticks);
- if ticks > maxticks then break;
+ inc(ticks, GoInfo.Ticks);
+ if ticks > maxticks then
+ break;
- if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support
- if Push(ticks, Actions, AltMe, Me^.Message) then
- with Stack.States[Pred(Stack.Count)] do
- begin
- if Me^.dX.isNegative then AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0)
- else AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0);
- AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0);
- AddAction(MadeActions, aia_HJump, 0, 350, 0, 0);
- if Me^.dX.isNegative then AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0)
- else AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0);
- end;
- if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support
- if Push(ticks, Actions, AltMe, Me^.Message) then
- with Stack.States[Pred(Stack.Count)] do
- AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
+ if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support
+ if Push(ticks, Actions, AltMe, Me^.Message) then
+ with Stack.States[Pred(Stack.Count)] do
+ begin
+ if Me^.dX.isNegative then
+ AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0)
+ else
+ AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0);
+
+ AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0);
+ AddAction(MadeActions, aia_HJump, 0, 350, 0, 0);
+
+ if Me^.dX.isNegative then
+ AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0)
+ else
+ AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0);
+ end;
+ if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support
+ if Push(ticks, Actions, AltMe, Me^.Message) then
+ with Stack.States[Pred(Stack.Count)] do
+ AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
- if not CanGo then break;
- inc(steps);
- Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
- Rate:= RatePlace(Me);
- if Rate > BestRate then
- begin
- BestActions:= Actions;
- BestActions.isWalkingToABetterPlace:= true;
- BestRate:= Rate;
- Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
- end
- else if Rate < BestRate then break;
- if ((Me^.State and gstAttacked) = 0)
- and ((steps mod 4) = 0) then TestAmmos(Actions, Me, true);
- if GoInfo.FallPix >= FallPixForBranching then
- Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
- end;
+ if not CanGo then
+ break;
+ inc(steps);
+ Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
+ Rate:= RatePlace(Me);
+ if Rate > BestRate then
+ begin
+ BestActions:= Actions;
+ BestActions.isWalkingToABetterPlace:= true;
+ BestRate:= Rate;
+ Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
+ end
+ else if Rate < BestRate then
+ break;
+ if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then
+ TestAmmos(Actions, Me, true);
+ if GoInfo.FallPix >= FallPixForBranching then
+ Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
+ end;
- if BestRate > BaseRate then exit
- end
+ if BestRate > BaseRate then
+ exit
+ end
end;
function Think(Me: Pointer): ptrint;
@@ -283,8 +305,8 @@
switchAvailable:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch);
if (PGear(Me)^.State and gstAttacked) = 0 then
- if Targets.Count > 0 then
- begin
+ if Targets.Count > 0 then
+ begin
// iterate over current team hedgehogs
repeat
WalkMe:= CurrentTeam^.Hedgehogs[itHedgehog].Gear^;
@@ -318,7 +340,8 @@
or (itHedgehog = currHedgehogIndex)
or BestActions.isWalkingToABetterPlace;
- if (StartTicks > GameTicks - 1500) and (not StopThinking) then SDL_Delay(1000);
+ if (StartTicks > GameTicks - 1500) and (not StopThinking) then
+ SDL_Delay(1000);
if (BestActions.Score < -1023) and (not BestActions.isWalkingToABetterPlace) then
begin
@@ -326,8 +349,9 @@
AddAction(BestActions, aia_Skip, 0, 250, 0, 0);
end;
- end else
-else begin
+ end else
+else
+ begin
BackMe:= PGear(Me)^;
while (not StopThinking) and (BestActions.Count = 0) do
begin
@@ -337,7 +361,8 @@
Actions.Pos:= 0;
Actions.Score:= 0;
Walk(@WalkMe, Actions);
- if not StopThinking then SDL_Delay(100)
+ if not StopThinking then
+ SDL_Delay(100)
end
end;
@@ -349,7 +374,8 @@
procedure StartThink(Me: PGear);
begin
if ((Me^.State and (gstAttacking or gstHHJumping or gstMoving)) <> 0)
- or isInMultiShoot then exit;
+or isInMultiShoot then
+ exit;
//DeleteCI(Me); // this might break demo
Me^.State:= Me^.State or gstHHThinking;
@@ -365,10 +391,10 @@
FillTargets;
if Targets.Count = 0 then
- begin
- OutError('AI: no targets!?', false);
- exit
- end;
+ begin
+ OutError('AI: no targets!?', false);
+ exit
+ end;
FillBonuses((Me^.State and gstAttacked) <> 0);
AddFileLog('Enter Think Thread');
@@ -385,24 +411,28 @@
cStopThinkTime = 40;
begin
with CurrentHedgehog^ do
- if (Gear <> nil)
- and ((Gear^.State and gstHHDriven) <> 0)
- and (TurnTimeLeft < cHedgehogTurnTime - 50) then
+ if (Gear <> nil)
+ and ((Gear^.State and gstHHDriven) <> 0)
+ and (TurnTimeLeft < cHedgehogTurnTime - 50) then
if ((Gear^.State and gstHHThinking) = 0) then
- if (BestActions.Pos >= BestActions.Count)
- and (TurnTimeLeft > cStopThinkTime) then
- begin
- if Gear^.Message <> 0 then
- begin
- StopMessages(Gear^.Message);
- TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true);
- end;
- if Gear^.Message <> 0 then exit;
- StartThink(Gear);
- StartTicks:= GameTicks
- end else ProcessAction(BestActions, Gear)
+ if (BestActions.Pos >= BestActions.Count)
+ and (TurnTimeLeft > cStopThinkTime) then
+ begin
+ if Gear^.Message <> 0 then
+ begin
+ StopMessages(Gear^.Message);
+ TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true);
+ end;
+ if Gear^.Message <> 0 then
+ exit;
+ StartThink(Gear);
+ StartTicks:= GameTicks
+
+ end else
+ ProcessAction(BestActions, Gear)
else if ((GameTicks - StartTicks) > cMaxAIThinkTime)
- or (TurnTimeLeft <= cStopThinkTime) then StopThinking:= true
+ or (TurnTimeLeft <= cStopThinkTime) then
+ StopThinking:= true
end;
procedure initModule;