23 procedure ProcessBot; |
23 procedure ProcessBot; |
24 procedure FreeActionsList; |
24 procedure FreeActionsList; |
25 |
25 |
26 implementation |
26 implementation |
27 uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc, |
27 uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc, |
28 uAmmos, uConsole, uCollisions{$IFDEF UNIX}, cthreads{$ENDIF}; |
28 uAmmos, uConsole, uCollisions, SysUtils{$IFDEF UNIX}, cthreads{$ENDIF}; |
29 |
29 |
30 var BestActions: TActions; |
30 var BestActions: TActions; |
31 ThinkThread: THandle = 0; |
31 CanUseAmmo: array [TAmmoType] of boolean; |
32 StopThinking: boolean; |
32 StopThinking: boolean; |
33 CanUseAmmo: array [TAmmoType] of boolean; |
33 ThinkThread: THandle; |
34 |
34 hasThread: LongInt = 0; |
|
35 |
35 procedure FreeActionsList; |
36 procedure FreeActionsList; |
36 begin |
37 begin |
37 {$IFDEF DEBUGFILE}AddFileLog('FreeActionsList called');{$ENDIF} |
38 {$IFDEF DEBUGFILE}AddFileLog('FreeActionsList called');{$ENDIF} |
38 if ThinkThread <> 0 then |
39 if hasThread <> 0 then |
39 begin |
40 begin |
40 {$IFDEF DEBUGFILE}AddFileLog('Waiting AI thread to finish');{$ENDIF} |
41 {$IFDEF DEBUGFILE}AddFileLog('Waiting AI thread to finish');{$ENDIF} |
41 StopThinking:= true; |
42 StopThinking:= true; |
42 WaitForThreadTerminate(ThinkThread, 5000); |
43 repeat |
43 ThinkThread:= 0 |
44 SDL_Delay(10) |
|
45 until hasThread = 0 |
44 end; |
46 end; |
45 |
47 |
46 with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do |
48 with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do |
47 if Gear <> nil then |
49 if Gear <> nil then |
48 if BotLevel <> 0 then |
50 if BotLevel <> 0 then |
62 a, aa: TAmmoType; |
64 a, aa: TAmmoType; |
63 begin |
65 begin |
64 BotLevel:= PHedgehog(Me^.Hedgehog)^.BotLevel; |
66 BotLevel:= PHedgehog(Me^.Hedgehog)^.BotLevel; |
65 |
67 |
66 for i:= 0 to Pred(Targets.Count) do |
68 for i:= 0 to Pred(Targets.Count) do |
67 if (Targets.ar[i].Score >= 0) then |
69 if (Targets.ar[i].Score >= 0) and (not StopThinking) then |
68 begin |
70 begin |
69 with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do |
71 with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do |
70 a:= Ammo^[CurSlot, CurAmmo].AmmoType; |
72 a:= Ammo^[CurSlot, CurAmmo].AmmoType; |
71 aa:= a; |
73 aa:= a; |
72 repeat |
74 repeat |
101 AddAction(BestActions, aia_AwareExpl, ExplR, 10, ExplX, ExplY); |
103 AddAction(BestActions, aia_AwareExpl, ExplR, 10, ExplX, ExplY); |
102 end |
104 end |
103 end; |
105 end; |
104 if a = High(TAmmoType) then a:= Low(TAmmoType) |
106 if a = High(TAmmoType) then a:= Low(TAmmoType) |
105 else inc(a) |
107 else inc(a) |
106 until (a = aa) or (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].AttacksNum > 0) |
108 until (a = aa) or |
|
109 (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].AttacksNum > 0) or |
|
110 StopThinking |
107 end |
111 end |
108 end; |
112 end; |
109 |
113 |
110 procedure Walk(Me: PGear); |
114 procedure Walk(Me: PGear); |
111 const FallPixForBranching = cHHRadius * 2 + 8; |
115 const FallPixForBranching = cHHRadius * 2 + 8; |
239 |
243 |
240 function Think(Me: Pointer): ptrint; |
244 function Think(Me: Pointer): ptrint; |
241 var BackMe, WalkMe: TGear; |
245 var BackMe, WalkMe: TGear; |
242 StartTicks: Longword; |
246 StartTicks: Longword; |
243 begin |
247 begin |
|
248 InterlockedIncrement(hasThread); |
244 StartTicks:= GameTicks; |
249 StartTicks:= GameTicks; |
245 BestActions.Count:= 0; |
|
246 BestActions.Pos:= 0; |
|
247 BestActions.Score:= Low(integer); |
|
248 BackMe:= PGear(Me)^; |
250 BackMe:= PGear(Me)^; |
249 WalkMe:= BackMe; |
251 |
250 if (PGear(Me)^.State and gstAttacked) = 0 then |
252 if (PGear(Me)^.State and gstAttacked) = 0 then |
251 if Targets.Count > 0 then |
253 if Targets.Count > 0 then |
252 begin |
254 begin |
|
255 WalkMe:= BackMe; |
253 Walk(@WalkMe); |
256 Walk(@WalkMe); |
254 if (StartTicks > GameTicks - 1500) and not StopThinking then SDL_Delay(2000); |
257 if (StartTicks > GameTicks - 1500) and not StopThinking then SDL_Delay(2000); |
255 if BestActions.Score < -1023 then |
258 if BestActions.Score < -1023 then |
256 begin |
259 begin |
257 BestActions.Count:= 0; |
260 BestActions.Count:= 0; |
258 AddAction(BestActions, aia_Skip, 0, 250, 0, 0); |
261 AddAction(BestActions, aia_Skip, 0, 250, 0, 0); |
259 end; |
262 end; |
260 end else |
263 end else |
261 else begin |
264 else begin |
262 Walk(@WalkMe); |
|
263 while (not StopThinking) and (BestActions.Count = 0) do |
265 while (not StopThinking) and (BestActions.Count = 0) do |
264 begin |
266 begin |
265 SDL_Delay(100); |
|
266 FillBonuses(true); |
267 FillBonuses(true); |
267 WalkMe:= BackMe; |
268 WalkMe:= BackMe; |
268 Walk(@WalkMe) |
269 Walk(@WalkMe); |
|
270 if not StopThinking then SDL_Delay(100) |
269 end |
271 end |
270 end; |
272 end; |
271 PGear(Me)^.State:= PGear(Me)^.State and not gstHHThinking; |
273 PGear(Me)^.State:= PGear(Me)^.State and not gstHHThinking; |
272 Think:= 0 |
274 Think:= 0; |
|
275 InterlockedDecrement(hasThread) |
273 end; |
276 end; |
274 |
277 |
275 procedure StartThink(Me: PGear); |
278 procedure StartThink(Me: PGear); |
276 var a: TAmmoType; |
279 var a: TAmmoType; |
277 begin |
280 begin |
279 or isInMultiShoot then exit; |
282 or isInMultiShoot then exit; |
280 |
283 |
281 DeleteCI(Me); // don't let collision info in Land to confuse AI |
284 DeleteCI(Me); // don't let collision info in Land to confuse AI |
282 Me^.State:= Me^.State or gstHHThinking; |
285 Me^.State:= Me^.State or gstHHThinking; |
283 Me^.Message:= 0; |
286 Me^.Message:= 0; |
|
287 |
|
288 BestActions.Count:= 0; |
|
289 BestActions.Pos:= 0; |
|
290 BestActions.Score:= Low(integer); |
|
291 |
284 StopThinking:= false; |
292 StopThinking:= false; |
285 ThinkingHH:= Me; |
293 ThinkingHH:= Me; |
|
294 |
286 FillTargets; |
295 FillTargets; |
287 if Targets.Count = 0 then |
296 if Targets.Count = 0 then |
288 begin |
297 begin |
289 OutError('AI: no targets!?', false); |
298 OutError('AI: no targets!?', false); |
290 exit |
299 exit |
296 BeginThread(@Think, Me, ThinkThread) |
305 BeginThread(@Think, Me, ThinkThread) |
297 end; |
306 end; |
298 |
307 |
299 procedure ProcessBot; |
308 procedure ProcessBot; |
300 const StartTicks: Longword = 0; |
309 const StartTicks: Longword = 0; |
|
310 cStopThinkTime = 40; |
301 begin |
311 begin |
302 with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do |
312 with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do |
303 if (Gear <> nil) |
313 if (Gear <> nil) |
304 and ((Gear^.State and gstHHDriven) <> 0) |
314 and ((Gear^.State and gstHHDriven) <> 0) |
305 and (TurnTimeLeft < cHedgehogTurnTime - 50) then |
315 and (TurnTimeLeft < cHedgehogTurnTime - 50) then |
306 if ((Gear^.State and gstHHThinking) = 0) then |
316 if ((Gear^.State and gstHHThinking) = 0) then |
307 if (BestActions.Pos >= BestActions.Count) then |
317 if (BestActions.Pos >= BestActions.Count) |
|
318 and (TurnTimeLeft > cStopThinkTime) then |
308 begin |
319 begin |
309 StartThink(Gear); |
320 StartThink(Gear); |
310 StartTicks:= GameTicks |
321 StartTicks:= GameTicks |
311 end else ProcessAction(BestActions, Gear) |
322 end else ProcessAction(BestActions, Gear) |
312 else if (GameTicks - StartTicks) > cMaxAIThinkTime then StopThinking:= true |
323 else if ((GameTicks - StartTicks) > cMaxAIThinkTime) |
313 end; |
324 or (TurnTimeLeft <= cStopThinkTime) then StopThinking:= true |
314 |
325 end; |
315 |
326 |
316 end. |
327 end. |