diff -r 206aabea2229 -r a03c2d037e24 hedgewars/uAI.pas --- 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.