# HG changeset patch # User unc0rr # Date 1171207999 0 # Node ID 9f8f22094c0e667f474b6ef11037c0d07e47c456 # Parent b0f693024b50e4f55cf3a5d4c635acc847a90dac AI thinks in separate thread diff -r b0f693024b50 -r 9f8f22094c0e hedgewars/CMakeLists.txt --- a/hedgewars/CMakeLists.txt Sun Feb 11 12:27:45 2007 +0000 +++ b/hedgewars/CMakeLists.txt Sun Feb 11 15:33:19 2007 +0000 @@ -11,7 +11,6 @@ uAIActions.pas uAIAmmoTests.pas uAIMisc.pas - uAIThinkStack.pas uAmmos.pas uCollisions.pas uConsole.pas diff -r b0f693024b50 -r 9f8f22094c0e hedgewars/SDLh.pas --- a/hedgewars/SDLh.pas Sun Feb 11 12:27:45 2007 +0000 +++ b/hedgewars/SDLh.pas Sun Feb 11 15:33:19 2007 +0000 @@ -188,6 +188,9 @@ PLongWordArray = ^TLongWordArray; TLongWordArray = array[0..16383] of LongWord; + PSDL_Thread = Pointer; + PSDL_mutex = Pointer; + function SDL_Init(flags: Longword): LongInt; cdecl; external SDLLibName; procedure SDL_Quit; cdecl; external SDLLibName; function SDL_VideoDriverName(var namebuf; maxlen: LongInt): PChar; cdecl; external SDLLibName; @@ -233,6 +236,13 @@ procedure SDL_WM_SetCaption(title: PChar; icon: PChar); cdecl; external SDLLibName; +function SDL_CreateThread(fn: pointer; data: pointer): PSDL_Thread; cdecl; external SDLLibName; +procedure SDL_WaitThread(thread: PSDL_Thread; status: PLongInt); cdecl; external SDLLibName; +function SDL_CreateMutex: PSDL_mutex; cdecl; external SDLLibName; +procedure SDL_DestroyMutex(mutex: PSDL_mutex); cdecl; external SDLLibName; +function SDL_LockMutex(mutex: PSDL_mutex): LongInt; cdecl; external SDLLibName name 'SDL_mutexP'; +function SDL_UnlockMutex(mutex: PSDL_mutex): LongInt; cdecl; external SDLLibName name 'SDL_mutexV'; + (* TTF *) const {$IFDEF WIN32} diff -r b0f693024b50 -r 9f8f22094c0e hedgewars/uAI.pas --- a/hedgewars/uAI.pas Sun Feb 11 12:27:45 2007 +0000 +++ b/hedgewars/uAI.pas Sun Feb 11 15:33:19 2007 +0000 @@ -20,21 +20,28 @@ interface uses uFloat; {$INCLUDE options.inc} -procedure ProcessBot(FrameNo: Longword); +procedure ProcessBot; procedure FreeActionsList; implementation uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc, - uAIThinkStack, uAmmos; + uAmmos; var BestActions: TActions; + ThinkThread: PSDL_Thread = nil; + StopThinking: boolean; CanUseAmmo: array [TAmmoType] of boolean; - AIThinkStart: Longword; - isThinking: boolean = false; procedure FreeActionsList; begin -isThinking:= false; +{$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; BestActions.Count:= 0; BestActions.Pos:= 0 end; @@ -46,6 +53,7 @@ a, aa: TAmmoType; begin BotLevel:= PHedgehog(Me^.Hedgehog)^.BotLevel; + for i:= 0 to Pred(Targets.Count) do if (Targets.ar[i].Score >= 0) then begin @@ -67,7 +75,7 @@ else if (Angle < 0) then AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0); if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then begin - Angle:= LongInt(Me^.Angle) - Abs(Angle); + Angle:= integer(Me^.Angle) - Abs(Angle); if Angle > 0 then begin AddAction(BestActions, aia_Up, aim_push, 500, 0, 0); @@ -86,42 +94,102 @@ end; if a = High(TAmmoType) then a:= Low(TAmmoType) else inc(a) - until (a = aa) or (PHedgehog(Me^.Hedgehog)^.AttacksNum > 0) + until (a = aa) or (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].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; + var Result: 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; + Push:= Result + end; + + procedure Pop(var Ticks: Longword; var Actions: TActions; var 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; + while (i < Stack.Count) do + begin + if(not(hwAbs(Stack.States[i].Hedgehog.X - Me^.X) + + hwAbs(Stack.States[i].Hedgehog.Y - Me^.Y) > 2)) and + (Stack.States[i].Hedgehog.Message = Me^.Message) then exit(true); + inc(i) + end; + PosInThinkStack:= false + end; + + var Actions: TActions; - ticks, maxticks, steps, BotLevel: Longword; - BaseRate, Rate: LongInt; + ticks, maxticks, steps, BotLevel, tmp: Longword; + BaseRate, BestRate, 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; + else maxticks:= TurnTimeLeft; -BaseRate:= RatePlace(Me); +if (Me^.State and gstAttacked) = 0 then TestAmmos(Actions, Me); +BestRate:= RatePlace(Me); +BaseRate:= max(BestRate, 0); -repeat - if not Pop(ticks, Actions, Me^) then - begin - isThinking:= false; - exit - end; +while (Stack.Count > 0) and not StopThinking do + begin + Pop(ticks, Actions, Me^); - AddAction(Actions, Me^.Message, aim_push, 10, 0, 0); + AddAction(Actions, Me^.Message, aim_push, 250, 0, 0); if (Me^.Message and gm_Left) <> 0 then AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0) else AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0); AddAction(Actions, Me^.Message, aim_release, 0, 0, 0); steps:= 0; - if ((Me^.State and gstAttacked) = 0) then TestAmmos(Actions, Me); - while not PosInThinkStack(Me) do + while (not StopThinking) and (not PosInThinkStack(Me)) do begin CanGo:= HHGo(Me, @AltMe, GoInfo); inc(ticks, GoInfo.Ticks); @@ -129,128 +197,107 @@ if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support if Push(ticks, Actions, AltMe, Me^.Message) then - with ThinkStack.States[Pred(ThinkStack.Count)] do + with Stack.States[Pred(Stack.Count)] do begin AddAction(MadeActions, aia_HJump, 0, 305, 0, 0); AddAction(MadeActions, aia_HJump, 0, 350, 0, 0); - if (Me^.dX < 0) then AddAction(MadeActions, aia_WaitXL, hwRound(AltMe.X), 0, 0, 0) - else AddAction(MadeActions, aia_WaitXR, hwRound(AltMe.X), 0, 0, 0); end; if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support if Push(ticks, Actions, AltMe, Me^.Message) then - with ThinkStack.States[Pred(ThinkStack.Count)] do - begin + with Stack.States[Pred(Stack.Count)] do AddAction(MadeActions, aia_LJump, 0, 305, 0, 0); - if (Me^.dX < 0) then AddAction(MadeActions, aia_WaitXL, hwRound(AltMe.X), 0, 0, 0) - else AddAction(MadeActions, aia_WaitXR, hwRound(AltMe.X), 0, 0, 0); - end; + if not CanGo then break; inc(steps); Actions.actions[Actions.Count - 2].Param:= hwRound(Me^.X); Rate:= RatePlace(Me); - if Rate > BaseRate then + if Rate > BestRate then begin BestActions:= Actions; - BestActions.Score:= 1; - isThinking:= false; - exit + BestRate:= Rate; + Me^.State:= Me^.State or gstAttacked // we have better place, go there and don't use ammo end - else if Rate < BaseRate then break; + else if Rate < BestRate 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 ((Me^.State and gstAttacked) = 0) - and ((steps mod 4) = 0) then - begin - TestAmmos(Actions, Me); - if SDL_GetTicks - AIThinkStart >= Pred(cTimerInterval) then - begin - dec(Actions.Count, 3); - Push(ticks, Actions, Me^, Me^.Message); - exit - end - end - end; -until false + if BestRate > BaseRate then exit + end end; -procedure Think(Me: PGear); +procedure Think(Me: PGear); cdecl; var BackMe, WalkMe: TGear; + StartTicks: Longword; begin -AIThinkStart:= SDL_GetTicks; +StartTicks:= GameTicks; +BestActions.Count:= 0; +BestActions.Pos:= 0; +BestActions.Score:= Low(integer); BackMe:= Me^; WalkMe:= BackMe; if (Me^.State and gstAttacked) = 0 then if Targets.Count > 0 then begin Walk(@WalkMe); - if not isThinking then + if (StartTicks > GameTicks - 1500) and not StopThinking then SDL_Delay(2000); + if BestActions.Score < -1023 then begin - if BestActions.Score < -1023 then - begin - BestActions.Count:= 0; - AddAction(BestActions, aia_Skip, 0, 250, 0, 0); - end; - Me^.State:= Me^.State and not gstHHThinking - end + BestActions.Count:= 0; + AddAction(BestActions, aia_Skip, 0, 250, 0, 0); + end; end else else begin - FillBonuses(true); Walk(@WalkMe); - AddAction(BestActions, aia_Wait, GameTicks + 100, 100, 0, 0); - end + 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 end; procedure StartThink(Me: PGear); var a: TAmmoType; - tmp: LongInt; 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!?', false); 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) +end; -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(LongInt); - -Think(Me) -end; - -procedure ProcessBot(FrameNo: Longword); -const LastFrameNo: Longword = 0; +procedure ProcessBot; +const StartTicks: Longword = 0; begin with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do if (Gear <> nil) and ((Gear^.State and gstHHDriven) <> 0) and (TurnTimeLeft < cHedgehogTurnTime - 50) then - if not isThinking then - if (BestActions.Pos >= BestActions.Count) then StartThink(Gear) - else ProcessAction(BestActions, Gear) - else if FrameNo <> LastFrameNo then - begin - LastFrameNo:= FrameNo; - Think(Gear) - end; + 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 end; + end. diff -r b0f693024b50 -r 9f8f22094c0e hedgewars/uAIActions.pas --- a/hedgewars/uAIActions.pas Sun Feb 11 12:27:45 2007 +0000 +++ b/hedgewars/uAIActions.pas Sun Feb 11 15:33:19 2007 +0000 @@ -59,7 +59,7 @@ procedure ProcessAction(var Actions: TActions; Me: PGear); implementation -uses uMisc, uTeams, uConsts, uConsole, uAIMisc; +uses uMisc, uTeams, uConsts, uConsole, uAIMisc, uAI; const ActionIdToStr: array[0..6] of string[16] = ( {aia_none} '', @@ -150,14 +150,16 @@ else if hwRound(Me^.X) < Param then begin OutError('AI: WaitXL assert', false); - Actions.Count:= 0 + FreeActionsList; + exit end else begin CheckHang; exit end; aia_WaitXR: if hwRound(Me^.X) = Param then Time:= GameTicks else if hwRound(Me^.X) > Param then begin OutError('AI: WaitXR assert', false); - Actions.Count:= 0 + FreeActionsList; + exit end else begin CheckHang; exit end; aia_LookLeft: if not Me^.dX.isNegative then diff -r b0f693024b50 -r 9f8f22094c0e hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Sun Feb 11 12:27:45 2007 +0000 +++ b/hedgewars/uAIAmmoTests.pas Sun Feb 11 15:33:19 2007 +0000 @@ -24,9 +24,10 @@ function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; (*function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; +*) function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; -*) + type TAmmoTestProc = function (Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; const AmmoTests: array[TAmmoType] of TAmmoTestProc = ( @@ -34,15 +35,15 @@ {amClusterBomb} nil, {amBazooka} @TestBazooka, {amUFO} nil, -{amShotgun} @TestShotgun, +{amShotgun} nil,//@TestShotgun, {amPickHammer} nil, {amSkip} nil, {amRope} nil, {amMine} nil, {amDEagle} nil,//TestDesertEagle, {amDynamite} nil, -{amFirePunch} nil,//TestFirePunch, -{amBaseballBat} nil,//TestBaseballBat, +{amFirePunch} @TestFirePunch, +{amBaseballBat} @TestBaseballBat, {amParachute} nil, {amAirAttack} nil, {amMineStrike} nil, @@ -106,8 +107,8 @@ Score:= CheckTrace; if Result <= Score then begin - Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 8)); - Power:= hwRound(r * cMaxPower) - random((Level - 1) * 15 + 1); + Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 11)); + Power:= hwRound(r * cMaxPower) - random((Level - 1) * 17 + 1); ExplR:= 100; ExplX:= EX; ExplY:= EY; @@ -159,7 +160,7 @@ if Result < Score then begin Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level)); - Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 12); + Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 15); Time:= TestTime; ExplR:= 100; ExplX:= EX; @@ -232,38 +233,37 @@ if abs(Targ.X - x) + abs(Targ.Y - y) < 2 then Result:= max(0, (4 - d div 50) * 7 * 1024) else Result:= Low(LongInt) end; - +} function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; +var Result: LongInt; begin ExplR:= 0; -if (Level > 2) and (abs(Me.X - Targ.X) + abs(Me.Y - Targ.Y) >= 25) then - begin - Result:= BadTurn; - exit - end; +if (Level > 2) and not (hwAbs(Me^.X - Targ.X) + hwAbs(Me^.Y - Targ.Y) < 25) then + exit(BadTurn); + Time:= 0; Power:= 1; -Angle:= DxDy2AttackAngle(hwSign(Targ.X - Me.X), 1); -Result:= RateShove(Me, round(Me.X) + 10 * hwSign(Targ.X - Me.X), round(Me.Y), 15, 30); -if Result <= 0 then Result:= BadTurn +Angle:= DxDy2AttackAngle(hwSign(Targ.X - Me^.X), 1); +Result:= RateShove(Me, hwRound(Me^.X) + 10 * hwSign(Targ.X - Me^.X), hwRound(Me^.Y), 15, 30); +if Result <= 0 then Result:= BadTurn else inc(Result); +TestBaseballBat:= Result end; function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; -var i: LongInt; +var i, Result: LongInt; begin ExplR:= 0; -if (abs(Me.X - Targ.X) > 25) or (abs(Me.Y - 50 - Targ.Y) > 50) then - begin - Result:= BadTurn; - exit - end; Time:= 0; Power:= 1; -Angle:= DxDy2AttackAngle(hwSign(Targ.X - Me.X), 1); +Angle:= 0; +if (hwAbs(Me^.X - Targ.X) > 25) or (hwAbs(Me^.Y - 50 - Targ.Y) > 50) then + exit(BadTurn); + Result:= 0; for i:= 0 to 4 do - Result:= Result + RateShove(Me, round(Me.X) + 10 * hwSign(Targ.X - Me.X), round(Me.Y) - 20 * i - 5, 10, 30); -if Result <= 0 then Result:= BadTurn + Result:= Result + RateShove(Me, hwRound(Me^.X) + 10 * hwSign(Targ.X - Me^.X), hwRound(Me^.Y) - 20 * i - 5, 10, 30); +if Result <= 0 then Result:= BadTurn; +TestFirePunch:= Result end; -} + end. diff -r b0f693024b50 -r 9f8f22094c0e hedgewars/uAIMisc.pas --- a/hedgewars/uAIMisc.pas Sun Feb 11 12:27:45 2007 +0000 +++ b/hedgewars/uAIMisc.pas Sun Feb 11 15:33:19 2007 +0000 @@ -199,7 +199,7 @@ var i, dmg, Result: LongInt; begin Result:= 0; -for i:= 0 to Targets.Count do +for i:= 0 to Pred(Targets.Count) do with Targets.ar[i] do begin dmg:= r - hwRound(Distance(Point.x - x, Point.y - y)); @@ -241,7 +241,7 @@ if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) or TestCollisionYwithGear(Gear, -1)) then begin - Gear^.dY:= _0_15; + Gear^.dY:= -_0_15; Gear^.dX:= hwSign(Gear^.dX) * _0_15; Gear^.State:= Gear^.State or gstFalling or gstHHJumping end else exit(Result) @@ -253,7 +253,7 @@ if (Gear^.State and gstFalling) <> 0 then begin if (GoInfo.Ticks = 350) then - if (hwAbs(Gear^.dX) < cLittle + cLittle) and (Gear^.dY < -_0_02) then + if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then begin Gear^.dY:= -_0_25; Gear^.dX:= hwSign(Gear^.dX) * _0_02 diff -r b0f693024b50 -r 9f8f22094c0e hedgewars/uAIThinkStack.pas --- a/hedgewars/uAIThinkStack.pas Sun Feb 11 12:27:45 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -(* - * Hedgewars, a worms-like game - * Copyright (c) 2006 Andrey Korotaev - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - *) - -unit uAIThinkStack; -interface -uses uAIActions, uGears, uFloat; -{$INCLUDE options.inc} -const cBranchStackSize = 12; -type TStackEntry = record - WastedTicks: Longword; - MadeActions: TActions; - Hedgehog: TGear; - end; - -var ThinkStack: record - Count: Longword; - States: array[0..Pred(cBranchStackSize)] of TStackEntry; - end; - -function Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: LongInt): boolean; -function Pop(var Ticks: Longword; var Actions: TActions; var Me: TGear): boolean; -function PosInThinkStack(Me: PGear): boolean; -procedure ClearThinkStack; - -implementation - -function Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: LongInt): boolean; -var Result: boolean; -begin -Result:= (ThinkStack.Count < cBranchStackSize) and (Actions.Count < MAXACTIONS - 5); -if Result then - with ThinkStack.States[ThinkStack.Count] do - begin - WastedTicks:= Ticks; - MadeActions:= Actions; - Hedgehog:= Me; - Hedgehog.Message:= Dir; - inc(ThinkStack.Count) - end; -Push:= Result -end; - -function Pop(var Ticks: Longword; var Actions: TActions; var Me: TGear): boolean; -var Result: boolean; -begin -Result:= ThinkStack.Count > 0; -if Result then - begin - dec(ThinkStack.Count); - with ThinkStack.States[ThinkStack.Count] do - begin - Ticks:= WastedTicks; - Actions:= MadeActions; - Me:= Hedgehog - end - end; -Pop:= Result -end; - -function PosInThinkStack(Me: PGear): boolean; -var i: Longword; -begin -i:= 0; -while (i < ThinkStack.Count) do - begin - if (not (2 < hwAbs(ThinkStack.States[i].Hedgehog.X - Me^.X) + - hwAbs(ThinkStack.States[i].Hedgehog.Y - Me^.Y))) - and (ThinkStack.States[i].Hedgehog.Message = Me^.Message) then exit(true); - inc(i) - end; -PosInThinkStack:= false -end; - -procedure ClearThinkStack; -begin -ThinkStack.Count:= 0 -end; - -end. diff -r b0f693024b50 -r 9f8f22094c0e hedgewars/uGame.pas --- a/hedgewars/uGame.pas Sun Feb 11 12:27:45 2007 +0000 +++ b/hedgewars/uGame.pas Sun Feb 11 15:33:19 2007 +0000 @@ -53,7 +53,7 @@ if not CurrentTeam^.ExtDriven then begin with CurrentTeam^ do - if Hedgehogs[CurrHedgehog].BotLevel <> 0 then ProcessBot(Frames); + if Hedgehogs[CurrHedgehog].BotLevel <> 0 then ProcessBot; ProcessGears end else begin diff -r b0f693024b50 -r 9f8f22094c0e hedgewars/uMisc.pas --- a/hedgewars/uMisc.pas Sun Feb 11 12:27:45 2007 +0000 +++ b/hedgewars/uMisc.pas Sun Feb 11 15:33:19 2007 +0000 @@ -33,7 +33,7 @@ GameFlags : Longword = 0; TurnTimeLeft : Longword = 0; cHedgehogTurnTime: Longword = 45000; - cMaxAIThinkTime : Longword = 5000; + cMaxAIThinkTime : Longword = 9000; cCloudsNumber : LongInt = 9; cConsoleHeight : LongInt = 320;