--- a/hedgewars/uAI.pas Thu Oct 05 20:13:51 2006 +0000
+++ b/hedgewars/uAI.pas Sun Oct 08 18:17:52 2006 +0000
@@ -19,27 +19,21 @@
unit uAI;
interface
{$INCLUDE options.inc}
-procedure ProcessBot;
+procedure ProcessBot(FrameNo: Longword);
procedure FreeActionsList;
implementation
-uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc;
+uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc,
+ uAIThinkStack, uConsole;
var BestActions: TActions;
- ThinkThread: PSDL_Thread = nil;
- StopThinking: boolean;
CanUseAmmo: array [TAmmoType] of boolean;
+ AIThinkStart: Longword;
+ isThinking: boolean = false;
procedure FreeActionsList;
begin
-{$IFDEF DEBUGFILE}AddFileLog('FreeActionsList called');{$ENDIF}
-if ThinkThread <> nil then
- begin
- {$IFDEF DEBUGFILE}AddFileLog('Waiting AI thread to finish');{$ENDIF}
- StopThinking:= true;
- SDL_WaitThread(ThinkThread, nil);
- ThinkThread:= nil
- end;
+isThinking:= false;
BestActions.Count:= 0;
BestActions.Pos:= 0
end;
@@ -92,206 +86,160 @@
end;
if a = High(TAmmoType) then a:= Low(TAmmoType)
else inc(a)
- until (a = aa) or (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0)
+ until (a = aa) or (PHedgehog(Me.Hedgehog).AttacksNum > 0)
end
end;
procedure Walk(Me: PGear);
const FallPixForBranching = cHHRadius * 2 + 8;
- cBranchStackSize = 12;
-type TStackEntry = record
- WastedTicks: Longword;
- MadeActions: TActions;
- Hedgehog: TGear;
- end;
-
-var Stack: record
- Count: Longword;
- States: array[0..Pred(cBranchStackSize)] of TStackEntry;
- end;
-
- function Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer): boolean;
- begin
- Result:= (Stack.Count < cBranchStackSize) and (Actions.Count < MAXACTIONS - 5);
- if Result then
- with Stack.States[Stack.Count] do
- begin
- WastedTicks:= Ticks;
- MadeActions:= Actions;
- Hedgehog:= Me;
- Hedgehog.Message:= Dir;
- inc(Stack.Count)
- end
- end;
-
- procedure Pop(out Ticks: Longword; out Actions: TActions; out Me: TGear);
- begin
- dec(Stack.Count);
- with Stack.States[Stack.Count] do
- begin
- Ticks:= WastedTicks;
- Actions:= MadeActions;
- Me:= Hedgehog
- end
- end;
-
- function PosInThinkStack(Me: PGear): boolean;
- var i: Longword;
- begin
- i:= 0;
- Result:= false;
- while (i < Stack.Count) and not Result do
- begin
- Result:= (abs(Stack.States[i].Hedgehog.X - Me.X) +
- abs(Stack.States[i].Hedgehog.Y - Me.Y) <= 2)
- and (Stack.States[i].Hedgehog.Message = Me.Message);
- inc(i)
- end
- end;
-
-
var Actions: TActions;
- ticks, maxticks, steps, BotLevel, tmp: Longword;
- BaseRate, BestRate, Rate: integer;
+ ticks, maxticks, steps, BotLevel: Longword;
+ BaseRate, Rate: integer;
GoInfo: TGoInfo;
CanGo: boolean;
AltMe: TGear;
begin
-Actions.Count:= 0;
-Actions.Pos:= 0;
-Actions.Score:= 0;
-Stack.Count:= 0;
BotLevel:= PHedgehog(Me.Hedgehog).BotLevel;
-tmp:= random(2) + 1;
-Push(0, Actions, Me^, tmp);
-Push(0, Actions, Me^, tmp xor 3);
-
if (Me.State and gstAttacked) = 0 then maxticks:= max(0, TurnTimeLeft - 5000 - 4000 * BotLevel)
else maxticks:= TurnTimeLeft;
-if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me);
-BestRate:= RatePlace(Me);
-BaseRate:= max(BestRate, 0);
+
+BaseRate:= max(RatePlace(Me), 0);
-while (Stack.Count > 0) and not StopThinking do
- begin
- Pop(ticks, Actions, Me^);
-
+repeat
+ if not Pop(ticks, Actions, Me^) then
+ begin
+ isThinking:= false;
+ exit
+ end;
AddAction(Actions, Me.Message, aim_push, 250);
AddAction(Actions, aia_WaitX, round(Me.X), 0);
AddAction(Actions, Me.Message, aim_release, 0);
steps:= 0;
- while (not StopThinking) and (not PosInThinkStack(Me)) do
+ while not PosInThinkStack(Me) do
begin
+ if SDL_GetTicks - AIThinkStart > 3 then
+ begin
+ writetoconsole(inttostr(SDL_GetTicks - AIThinkStart) + ' ');
+ dec(Actions.Count, 3);
+ Push(ticks, Actions, Me^, Me^.Message);
+ exit
+ end;
+
CanGo:= HHGo(Me, @AltMe, GoInfo);
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
+ with ThinkStack.States[Pred(ThinkStack.Count)] do
begin
AddAction(MadeActions, aia_HJump, 0, 305);
AddAction(MadeActions, aia_HJump, 0, 350);
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
+ with ThinkStack.States[Pred(ThinkStack.Count)] do
AddAction(MadeActions, aia_LJump, 0, 305);
if not CanGo then break;
inc(steps);
Actions.actions[Actions.Count - 2].Param:= round(Me.X);
Rate:= RatePlace(Me);
- if Rate > BestRate then
+ if Rate > BaseRate then
begin
BestActions:= Actions;
- BestRate:= Rate;
- Me.State:= Me.State or gstAttacked // we have better place, go there and don't use ammo
+ BestActions.Score:= 1;
+ isThinking:= false;
+ exit
end
- else if Rate < BestRate then break;
+ else if Rate < BaseRate then break;
if ((Me.State and gstAttacked) = 0)
and ((steps mod 4) = 0) then TestAmmos(Actions, Me);
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
+until false
end;
-procedure Think(Me: PGear); cdecl;
+procedure Think(Me: PGear);
var BackMe, WalkMe: TGear;
- StartTicks: Longword;
+// StartTicks: Longword;
begin
-StartTicks:= GameTicks;
-BestActions.Count:= 0;
-BestActions.Pos:= 0;
-BestActions.Score:= Low(integer);
+AIThinkStart:= SDL_GetTicks;
BackMe:= Me^;
WalkMe:= BackMe;
if (Me.State and gstAttacked) = 0 then
if Targets.Count > 0 then
begin
Walk(@WalkMe);
- if (StartTicks > GameTicks - 1500) and not StopThinking then SDL_Delay(2000);
- if BestActions.Score < -1023 then
+ if not isThinking then
begin
- BestActions.Count:= 0;
- AddAction(BestActions, aia_Skip, 0, 250);
- end;
+ if BestActions.Score < -1023 then
+ begin
+ BestActions.Count:= 0;
+ AddAction(BestActions, aia_Skip, 0, 250);
+ end;
+ Me.State:= Me.State and not gstHHThinking
+ end
end else
else begin
- Walk(@WalkMe);
- while (not StopThinking) and (BestActions.Count = 0) do
- begin
- SDL_Delay(100);
- FillBonuses(true);
- WalkMe:= BackMe;
- Walk(@WalkMe)
- end
- end;
-Me.State:= Me.State and not gstHHThinking
+ FillBonuses(true);
+ Walk(@WalkMe)
+ end
end;
procedure StartThink(Me: PGear);
var a: TAmmoType;
+ tmp: integer;
begin
if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit;
+ThinkingHH:= Me;
+isThinking:= true;
+
+ClearThinkStack;
+
Me.State:= Me.State or gstHHThinking;
Me.Message:= 0;
-StopThinking:= false;
-ThinkingHH:= Me;
FillTargets;
if Targets.Count = 0 then
begin
OutError('AI: no targets!?');
exit
end;
+
FillBonuses((Me.State and gstAttacked) <> 0);
+
for a:= Low(TAmmoType) to High(TAmmoType) do
CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me.Hedgehog), a);
-{$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF}
-ThinkThread:= SDL_CreateThread(@Think, Me)
+
+BestActions.Count:= 0;
+BestActions.Pos:= 0;
+BestActions.Score:= 0;
+tmp:= random(2) + 1;
+Push(0, BestActions, Me^, tmp);
+Push(0, BestActions, Me^, tmp xor 3);
+BestActions.Score:= Low(integer);
+
+Think(Me)
end;
-procedure ProcessBot;
-const StartTicks: Longword = 0;
+procedure ProcessBot(FrameNo: Longword);
+const LastFrameNo: Longword = 0;
begin
+if FrameNo = LastFrameNo then exit;
+LastFrameNo:= FrameNo;
with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
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) then
- begin
- StartThink(Gear);
- StartTicks:= GameTicks
- end else ProcessAction(BestActions, Gear)
- else if (GameTicks - StartTicks) > cMaxAIThinkTime then StopThinking:= true
+ if not isThinking then
+ if (BestActions.Pos >= BestActions.Count) then StartThink(Gear)
+ else ProcessAction(BestActions, Gear)
+ else Think(Gear)
end;
end.