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); |
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); |