hedgewars/uAI.pas
changeset 8865 dd4035ee0f12
parent 8677 afb2b467f801
child 8884 08fe08651130
equal deleted inserted replaced
8862:85eb1f4b4a5f 8865:dd4035ee0f12
    28 procedure ProcessBot;
    28 procedure ProcessBot;
    29 procedure FreeActionsList;
    29 procedure FreeActionsList;
    30 
    30 
    31 implementation
    31 implementation
    32 uses uConsts, SDLh, uAIMisc, uAIAmmoTests, uAIActions,
    32 uses uConsts, SDLh, uAIMisc, uAIAmmoTests, uAIActions,
    33     uAmmos, SysUtils{$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF}, uTypes,
    33     uAmmos, SysUtils, uTypes,
    34     uVariables, uCommands, uUtils, uDebug, uAILandMarks;
    34     uVariables, uCommands, uUtils, uDebug, uAILandMarks;
    35 
    35 
    36 var BestActions: TActions;
    36 var BestActions: TActions;
    37     CanUseAmmo: array [TAmmoType] of boolean;
    37     CanUseAmmo: array [TAmmoType] of boolean;
    38     StopThinking: boolean;
    38     StopThinking: boolean;
    39 {$IFDEF USE_SDLTHREADS} 
       
    40     ThinkThread: PSDL_Thread = nil;
    39     ThinkThread: PSDL_Thread = nil;
    41 {$ELSE}
       
    42     ThinkThread: TThreadID;
       
    43 {$ENDIF}
       
    44     hasThread: LongInt;
       
    45     StartTicks: Longword;
    40     StartTicks: Longword;
    46 
    41 
    47 procedure FreeActionsList;
    42 procedure FreeActionsList;
    48 begin
    43 begin
    49     AddFileLog('FreeActionsList called');
    44     AddFileLog('FreeActionsList called');
    50     if hasThread <> 0 then
    45     if (ThinkThread <> nil) then
    51     begin
    46         SDL_WaitThread(ThinkThread, nil);
    52         AddFileLog('Waiting AI thread to finish');
    47     ThinkThread:=nil;
    53         StopThinking:= true;
       
    54         repeat
       
    55             SDL_Delay(10)
       
    56         until hasThread = 0
       
    57     end;
       
    58 
    48 
    59     with CurrentHedgehog^ do
    49     with CurrentHedgehog^ do
    60         if Gear <> nil then
    50         if Gear <> nil then
    61             if BotLevel <> 0 then
    51             if BotLevel <> 0 then
    62                 StopMessages(Gear^.Message);
    52                 StopMessages(Gear^.Message);
    63 
    53 
    64     BestActions.Count:= 0;
    54     BestActions.Count:= 0;
    65     BestActions.Pos:= 0
    55     BestActions.Pos:= 0
    66 end;
    56 end;
    67 
       
    68 
    57 
    69 
    58 
    70 const cBranchStackSize = 12;
    59 const cBranchStackSize = 12;
    71 type TStackEntry = record
    60 type TStackEntry = record
    72                    WastedTicks: Longword;
    61                    WastedTicks: Longword;
   121     if (Targets.ar[i].Score >= 0) and (not StopThinking) then
   110     if (Targets.ar[i].Score >= 0) and (not StopThinking) then
   122         begin
   111         begin
   123         with Me^.Hedgehog^ do
   112         with Me^.Hedgehog^ do
   124             a:= CurAmmoType;
   113             a:= CurAmmoType;
   125         aa:= a;
   114         aa:= a;
   126 {$IFDEF USE_SDLTHREADS}
   115         SDL_delay(0); // hint to let the context switch run
   127         SDL_delay(0);    //ThreadSwitch was only a hint
       
   128 {$ELSE}
       
   129         ThreadSwitch();
       
   130 {$ENDIF}       
       
   131         repeat
   116         repeat
   132         if (CanUseAmmo[a]) 
   117         if (CanUseAmmo[a])
   133             and ((not rareChecks) or ((AmmoTests[a].flags and amtest_Rare) = 0)) 
   118             and ((not rareChecks) or ((AmmoTests[a].flags and amtest_Rare) = 0))
   134             and ((i = 0) or ((AmmoTests[a].flags and amtest_NoTarget) = 0)) 
   119             and ((i = 0) or ((AmmoTests[a].flags and amtest_NoTarget) = 0))
   135             then
   120             then
   136             begin
   121             begin
   137 {$HINTS OFF}
   122 {$HINTS OFF}
   138             Score:= AmmoTests[a].proc(Me, Targets.ar[i].Point, BotLevel, ap);
   123             Score:= AmmoTests[a].proc(Me, Targets.ar[i].Point, BotLevel, ap);
   139 {$HINTS ON}
   124 {$HINTS ON}
   148 
   133 
   149                     if (ap.Angle > 0) then
   134                     if (ap.Angle > 0) then
   150                         AddAction(BestActions, aia_LookRight, 0, 200, 0, 0)
   135                         AddAction(BestActions, aia_LookRight, 0, 200, 0, 0)
   151                     else if (ap.Angle < 0) then
   136                     else if (ap.Angle < 0) then
   152                         AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0);
   137                         AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0);
   153                     
   138 
   154                     if (Ammoz[a].Ammo.Propz and ammoprop_Timerable) <> 0 then
   139                     if (Ammoz[a].Ammo.Propz and ammoprop_Timerable) <> 0 then
   155                         AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0);
   140                         AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0);
   156                         
   141 
   157                     if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then
   142                     if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then
   158                         begin
   143                         begin
   159                         dAngle:= LongInt(Me^.Angle) - Abs(ap.Angle);
   144                         dAngle:= LongInt(Me^.Angle) - Abs(ap.Angle);
   160                         if dAngle > 0 then
   145                         if dAngle > 0 then
   161                             begin
   146                             begin
   166                             begin
   151                             begin
   167                             AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0);
   152                             AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0);
   168                             AddAction(BestActions, aia_Down, aim_release, -dAngle, 0, 0)
   153                             AddAction(BestActions, aia_Down, aim_release, -dAngle, 0, 0)
   169                             end
   154                             end
   170                         end;
   155                         end;
   171                         
   156 
   172                     if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
   157                     if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
   173                         begin
   158                         begin
   174                         AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY)
   159                         AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY)
   175                         end;
   160                         end;
   176                         
   161 
   177                     if (Ammoz[a].Ammo.Propz and ammoprop_OscAim) <> 0 then
   162                     if (Ammoz[a].Ammo.Propz and ammoprop_OscAim) <> 0 then
   178                         begin
   163                         begin
   179                         AddAction(BestActions, aia_attack, aim_push, 350 + random(200), 0, 0);
   164                         AddAction(BestActions, aia_attack, aim_push, 350 + random(200), 0, 0);
   180                         AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
   165                         AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
   181                          
   166 
   182                         if abs(ap.Angle) > 32 then
   167                         if abs(ap.Angle) > 32 then
   183                            begin
   168                            begin
   184                            AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0);
   169                            AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0);
   185                            AddAction(BestActions, aia_Down, aim_release, 32, 0, 0);
   170                            AddAction(BestActions, aia_Down, aim_release, 32, 0, 0);
   186                            end;
   171                            end;
   187                         
   172 
   188                         AddAction(BestActions, aia_waitAngle, ap.Angle, 250, 0, 0);
   173                         AddAction(BestActions, aia_waitAngle, ap.Angle, 250, 0, 0);
   189                         AddAction(BestActions, aia_attack, aim_push, 1, 0, 0);
   174                         AddAction(BestActions, aia_attack, aim_push, 1, 0, 0);
   190                         AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
   175                         AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
   191                         end else
   176                         end else
   192                         if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then
   177                         if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then
   241 else
   226 else
   242     maxticks:= TurnTimeLeft;
   227     maxticks:= TurnTimeLeft;
   243 
   228 
   244 if (Me^.State and gstAttacked) = 0 then
   229 if (Me^.State and gstAttacked) = 0 then
   245     TestAmmos(Actions, Me, false);
   230     TestAmmos(Actions, Me, false);
   246     
   231 
   247 BestRate:= RatePlace(Me);
   232 BestRate:= RatePlace(Me);
   248 BaseRate:= Max(BestRate, 0);
   233 BaseRate:= Max(BestRate, 0);
   249 
   234 
   250 // switch to 'skip' if we can't move because of mouse cursor being shown
   235 // switch to 'skip' if we cannot move because of mouse cursor being shown
   251 if (Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
   236 if (Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
   252     AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0);
   237     AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0);
   253     
   238 
   254 if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0)) 
   239 if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0))
   255     and (GameFlags and gfArtillery = 0) then
   240     and (GameFlags and gfArtillery = 0) then
   256     begin
   241     begin
   257     tmp:= random(2) + 1;
   242     tmp:= random(2) + 1;
   258     Push(0, Actions, Me^, tmp);
   243     Push(0, Actions, Me^, tmp);
   259     Push(0, Actions, Me^, tmp xor 3);
   244     Push(0, Actions, Me^, tmp xor 3);
   260     
   245 
   261     while (Stack.Count > 0) and (not StopThinking) do
   246     while (Stack.Count > 0) and (not StopThinking) do
   262         begin
   247         begin
   263         Pop(ticks, Actions, Me^);
   248         Pop(ticks, Actions, Me^);
   264 
   249 
   265         AddAction(Actions, Me^.Message, aim_push, 250, 0, 0);
   250         AddAction(Actions, Me^.Message, aim_push, 250, 0, 0);
   266         if (Me^.Message and gmLeft) <> 0 then
   251         if (Me^.Message and gmLeft) <> 0 then
   267             AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
   252             AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
   268         else
   253         else
   269             AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0);
   254             AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0);
   270         
   255 
   271         steps:= 0;
   256         steps:= 0;
   272 
   257 
   273         while (not StopThinking) do
   258         while (not StopThinking) do
   274             begin
   259             begin
   275     {$HINTS OFF}
   260     {$HINTS OFF}
   278             oldticks:= ticks;
   263             oldticks:= ticks;
   279             inc(ticks, GoInfo.Ticks);
   264             inc(ticks, GoInfo.Ticks);
   280             if ticks > maxticks then
   265             if ticks > maxticks then
   281                 break;
   266                 break;
   282 
   267 
   283             if (BotLevel < 5) 
   268             if (BotLevel < 5)
   284                 and (GoInfo.JumpType = jmpHJump) 
   269                 and (GoInfo.JumpType = jmpHJump)
   285                 and (not checkMark(hwRound(Me^.X), hwRound(Me^.Y), markHJumped))
   270                 and (not checkMark(hwRound(Me^.X), hwRound(Me^.Y), markHJumped))
   286                 then // hjump support
   271                 then // hjump support
   287                 begin
   272                 begin
   288                 // check if we could go backwards and maybe ljump over a gap after this hjump
   273                 // check if we could go backwards and maybe ljump over a gap after this hjump
   289                 addMark(hwRound(Me^.X), hwRound(Me^.Y), markHJumped);
   274                 addMark(hwRound(Me^.X), hwRound(Me^.Y), markHJumped);
   293                         begin
   278                         begin
   294                         if (Me^.Message and gmLeft) <> 0 then
   279                         if (Me^.Message and gmLeft) <> 0 then
   295                             AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0)
   280                             AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0)
   296                         else
   281                         else
   297                             AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0);
   282                             AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0);
   298                             
   283 
   299                         AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0);
   284                         AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0);
   300                         AddAction(MadeActions, aia_HJump, 0, 350, 0, 0);
   285                         AddAction(MadeActions, aia_HJump, 0, 350, 0, 0);
   301                         end;
   286                         end;
   302                     // but first check walking forward
   287                     // but first check walking forward
   303                     Push(ticks, Stack.States[Pred(Stack.Count)].MadeActions, AltMe, Me^.Message)
   288                     Push(ticks, Stack.States[Pred(Stack.Count)].MadeActions, AltMe, Me^.Message)
   304                     end;
   289                     end;
   305                 end;
   290                 end;
   306             if (BotLevel < 3) 
   291             if (BotLevel < 3)
   307                 and (GoInfo.JumpType = jmpLJump) 
   292                 and (GoInfo.JumpType = jmpLJump)
   308                 and (not checkMark(hwRound(Me^.X), hwRound(Me^.Y), markLJumped))
   293                 and (not checkMark(hwRound(Me^.X), hwRound(Me^.Y), markLJumped))
   309                 then // ljump support
   294                 then // ljump support
   310                 begin
   295                 begin
   311                 addMark(hwRound(Me^.X), hwRound(Me^.Y), markLJumped);
   296                 addMark(hwRound(Me^.X), hwRound(Me^.Y), markLJumped);
   312                 // at final check where we go after jump walking backward
   297                 // at final check where we go after jump walking backward
   321                         AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
   306                         AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
   322                         end;
   307                         end;
   323 
   308 
   324                 // push current position so we proceed from it after checking jump+forward walk opportunities
   309                 // push current position so we proceed from it after checking jump+forward walk opportunities
   325                 if CanGo then Push(ticks, Actions, Me^, Me^.Message);
   310                 if CanGo then Push(ticks, Actions, Me^, Me^.Message);
   326                 
   311 
   327                 // first check where we go after jump walking forward
   312                 // first check where we go after jump walking forward
   328                 if Push(ticks, Actions, AltMe, Me^.Message) then
   313                 if Push(ticks, Actions, AltMe, Me^.Message) then
   329                     with Stack.States[Pred(Stack.Count)] do
   314                     with Stack.States[Pred(Stack.Count)] do
   330                         AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
   315                         AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
   331                 break
   316                 break
   332                 end;
   317                 end;
   333 
   318 
   334             // 'not CanGO' means we can't go straight, possible jumps are checked above
   319             // 'not CanGO' means we cannot go straight, possible jumps are checked above
   335             if not CanGo then
   320             if not CanGo then
   336                 break;
   321                 break;
   337             
   322 
   338              inc(steps);
   323              inc(steps);
   339              Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
   324              Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
   340              Rate:= RatePlace(Me);
   325              Rate:= RatePlace(Me);
   341              if Rate > BestRate then
   326              if Rate > BestRate then
   342                 begin
   327                 begin
   345                 BestRate:= Rate;
   330                 BestRate:= Rate;
   346                 Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
   331                 Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
   347                 end
   332                 end
   348             else if Rate < BestRate then
   333             else if Rate < BestRate then
   349                 break;
   334                 break;
   350                 
   335 
   351             if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then
   336             if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then
   352                 begin
   337                 begin
   353                 if (steps > 4) and checkMark(hwRound(Me^.X), hwRound(Me^.Y), markWalkedHere) then
   338                 if (steps > 4) and checkMark(hwRound(Me^.X), hwRound(Me^.Y), markWalkedHere) then
   354                     break;                    
   339                     break;
   355                 addMark(hwRound(Me^.X), hwRound(Me^.Y), markWalkedHere);
   340                 addMark(hwRound(Me^.X), hwRound(Me^.Y), markWalkedHere);
   356 
   341 
   357                 TestAmmos(Actions, Me, ticks shr 12 = oldticks shr 12);
   342                 TestAmmos(Actions, Me, ticks shr 12 = oldticks shr 12);
   358                 
   343 
   359                 end;
   344                 end;
   360                 
   345 
   361             if GoInfo.FallPix >= FallPixForBranching then
   346             if GoInfo.FallPix >= FallPixForBranching then
   362                 Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
   347                 Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
   363             end {while};
   348             end {while};
   364 
   349 
   365         if BestRate > BaseRate then
   350         if BestRate > BaseRate then
   366             exit
   351             exit
   367         end {while}
   352         end {while}
   368     end {if}
   353     end {if}
   369 end;
   354 end;
   370 
   355 
   371 function Think(Me: Pointer): ptrint;
   356 function Think(Me: PGear): LongInt; cdecl; export;
   372 var BackMe, WalkMe: TGear;
   357 var BackMe, WalkMe: TGear;
   373     switchCount: LongInt;
   358     switchCount: LongInt;
   374     StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i: Longword;
   359     StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i: Longword;
   375     switchImmediatelyAvailable: boolean;
   360     switchImmediatelyAvailable: boolean;
   376     Actions: TActions;
   361     Actions: TActions;
   377 begin
   362 begin
   378 InterlockedIncrement(hasThread);
   363 AddFileLog('Thread started');
   379 StartTicks:= GameTicks;
   364 StartTicks:= GameTicks;
   380 currHedgehogIndex:= CurrentTeam^.CurrHedgehog;
   365 currHedgehogIndex:= CurrentTeam^.CurrHedgehog;
   381 itHedgehog:= currHedgehogIndex;
   366 itHedgehog:= currHedgehogIndex;
   382 switchesNum:= 0;
   367 switchesNum:= 0;
   383 
   368 
   384 switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher);
   369 switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher);
   385 if PGear(Me)^.Hedgehog^.BotLevel <> 5 then
   370 if Me^.Hedgehog^.BotLevel <> 5 then
   386     switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch)
   371     switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch)
   387 else switchCount:= 0;
   372 else switchCount:= 0;
   388 
   373 
   389 if (PGear(Me)^.State and gstAttacked) = 0 then
   374 if (Me^.State and gstAttacked) = 0 then
   390     if Targets.Count > 0 then
   375     if Targets.Count > 0 then
   391         begin
   376         begin
   392         // iterate over current team hedgehogs
   377         // iterate over current team hedgehogs
   393         repeat
   378         repeat
   394             WalkMe:= CurrentTeam^.Hedgehogs[itHedgehog].Gear^;
   379             WalkMe:= CurrentTeam^.Hedgehogs[itHedgehog].Gear^;
   400                 begin
   385                 begin
   401                 if not switchImmediatelyAvailable  then
   386                 if not switchImmediatelyAvailable  then
   402                     begin
   387                     begin
   403                     // when AI has to use switcher, make it cost smth unless they have a lot of switches
   388                     // when AI has to use switcher, make it cost smth unless they have a lot of switches
   404                     if (switchCount < 10) then Actions.Score:= (-27+switchCount*3)*4000;
   389                     if (switchCount < 10) then Actions.Score:= (-27+switchCount*3)*4000;
   405                     AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0);                    
   390                     AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0);
   406                     AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0);
   391                     AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0);
   407                     AddAction(Actions, aia_attack, aim_release, 1, 0, 0);
   392                     AddAction(Actions, aia_attack, aim_release, 1, 0, 0);
   408                     end;
   393                     end;
   409                 for i:= 1 to switchesNum do
   394                 for i:= 1 to switchesNum do
   410                     AddAction(Actions, aia_Switch, 0, 300 + random(200), 0, 0);
   395                     AddAction(Actions, aia_Switch, 0, 300 + random(200), 0, 0);
   414             // find another hog in team
   399             // find another hog in team
   415             repeat
   400             repeat
   416                 itHedgehog:= Succ(itHedgehog) mod CurrentTeam^.HedgehogsNumber;
   401                 itHedgehog:= Succ(itHedgehog) mod CurrentTeam^.HedgehogsNumber;
   417             until (itHedgehog = currHedgehogIndex) or ((CurrentTeam^.Hedgehogs[itHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[itHedgehog].Effects[heFrozen]=0));
   402             until (itHedgehog = currHedgehogIndex) or ((CurrentTeam^.Hedgehogs[itHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[itHedgehog].Effects[heFrozen]=0));
   418 
   403 
   419 
       
   420             inc(switchesNum);
   404             inc(switchesNum);
   421         until (not (switchImmediatelyAvailable or (switchCount > 0)))
   405         until (not (switchImmediatelyAvailable or (switchCount > 0)))
   422             or StopThinking 
   406             or StopThinking
   423             or (itHedgehog = currHedgehogIndex)
   407             or (itHedgehog = currHedgehogIndex)
   424             or BestActions.isWalkingToABetterPlace;
   408             or BestActions.isWalkingToABetterPlace;
   425 
   409 
   426         if (StartTicks > GameTicks - 1500) and (not StopThinking) then
   410         if (StartTicks > GameTicks - 1500) and (not StopThinking) then
   427             SDL_Delay(1000);
   411             SDL_Delay(1000);
   433             end;
   417             end;
   434 
   418 
   435         end else SDL_Delay(100)
   419         end else SDL_Delay(100)
   436 else
   420 else
   437     begin
   421     begin
   438     BackMe:= PGear(Me)^;
   422     BackMe:= Me^;
   439     while (not StopThinking) and (BestActions.Count = 0) do
   423     while (not StopThinking) and (BestActions.Count = 0) do
   440         begin
   424         begin
   441 (*
   425 (*
   442         // 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
   426         // 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
   443         if SuddenDeathDmg and ((hwRound(BackMe.Y)+cWaterRise*2) > cWaterLine) then
   427         if SuddenDeathDmg and ((hwRound(BackMe.Y)+cWaterRise*2) > cWaterLine) then
   452         if not StopThinking then
   436         if not StopThinking then
   453             SDL_Delay(100)
   437             SDL_Delay(100)
   454         end
   438         end
   455     end;
   439     end;
   456 
   440 
   457 PGear(Me)^.State:= PGear(Me)^.State and (not gstHHThinking);
   441 Me^.State:= Me^.State and (not gstHHThinking);
       
   442 ThinkThread:= nil;
   458 Think:= 0;
   443 Think:= 0;
   459 InterlockedDecrement(hasThread)
       
   460 end;
   444 end;
   461 
   445 
   462 procedure StartThink(Me: PGear);
   446 procedure StartThink(Me: PGear);
   463 begin
   447 begin
   464 if ((Me^.State and (gstAttacking or gstHHJumping or gstMoving)) <> 0)
   448 if ((Me^.State and (gstAttacking or gstHHJumping or gstMoving)) <> 0)
   485     exit
   469     exit
   486     end;
   470     end;
   487 
   471 
   488 FillBonuses((Me^.State and gstAttacked) <> 0);
   472 FillBonuses((Me^.State and gstAttacked) <> 0);
   489 AddFileLog('Enter Think Thread');
   473 AddFileLog('Enter Think Thread');
   490 {$IFDEF USE_SDLTHREADS}
   474 ThinkThread:= SDL_CreateThread(@Think{$IFDEF SDL13}, 'think'{$ENDIF}, Me);
   491 ThinkThread := SDL_CreateThread(@Think{$IFDEF SDL13}, nil{$ENDIF}, Me);
       
   492 {$ELSE}
       
   493 BeginThread(@Think, Me, ThinkThread);
       
   494 {$ENDIF}
       
   495 AddFileLog('Thread started');
       
   496 end;
   475 end;
   497 
   476 
   498 //var scoreShown: boolean = false;
   477 //var scoreShown: boolean = false;
   499 
   478 
   500 procedure ProcessBot;
   479 procedure ProcessBot;
   511                 if Gear^.Message <> 0 then
   490                 if Gear^.Message <> 0 then
   512                     begin
   491                     begin
   513                     StopMessages(Gear^.Message);
   492                     StopMessages(Gear^.Message);
   514                     TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true);
   493                     TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true);
   515                     end;
   494                     end;
   516                     
   495 
   517                 if Gear^.Message <> 0 then
   496                 if Gear^.Message <> 0 then
   518                     exit;
   497                     exit;
   519                     
   498 
   520                 //scoreShown:= false;   
   499                 //scoreShown:= false;
   521                 StartThink(Gear);
   500                 StartThink(Gear);
   522                 StartTicks:= GameTicks
   501                 StartTicks:= GameTicks
   523                 
   502 
   524             end else
   503             end else
   525                 begin
   504                 begin
   526                 {if not scoreShown then
   505                 {if not scoreShown then
   527                     begin
   506                     begin
   528                     if BestActions.Score > 0 then ParseCommand('/say Expected score = ' + inttostr(BestActions.Score div 1024), true);
   507                     if BestActions.Score > 0 then ParseCommand('/say Expected score = ' + inttostr(BestActions.Score div 1024), true);
   535                 StopThinking:= true
   514                 StopThinking:= true
   536 end;
   515 end;
   537 
   516 
   538 procedure initModule;
   517 procedure initModule;
   539 begin
   518 begin
   540     hasThread:= 0;
       
   541     StartTicks:= 0;
   519     StartTicks:= 0;
   542     ThinkThread:= ThinkThread;
   520     ThinkThread:= nil;
   543 end;
   521 end;
   544 
   522 
   545 procedure freeModule;
   523 procedure freeModule;
   546 begin
   524 begin
       
   525     if (ThinkThread <> nil) then
       
   526         SDL_KillThread(ThinkThread);
       
   527     ThinkThread:= nil;
   547     FreeActionsList();
   528     FreeActionsList();
   548 end;
   529 end;
   549 
   530 
   550 end.
   531 end.