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{$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF}, uTypes, |
34 uVariables, uCommands, uUtils, uDebug, uAILandMarks; |
34 uVariables, uCommands, uUtils, uDebug, uAILandMarks; |
35 |
35 |
|
36 {$IFDEF AI_MAINTHREAD} |
|
37 const |
|
38 mainThreadMaxThinkTime:Integer = 1500; |
|
39 {$ENDIF} |
|
40 |
36 var BestActions: TActions; |
41 var BestActions: TActions; |
37 CanUseAmmo: array [TAmmoType] of boolean; |
42 CanUseAmmo: array [TAmmoType] of boolean; |
38 StopThinking: boolean; |
43 StopThinking: boolean; |
39 {$IFDEF USE_SDLTHREADS} |
44 {$IFDEF USE_SDLTHREADS} |
40 ThinkThread: PSDL_Thread = nil; |
45 ThinkThread: PSDL_Thread = nil; |
41 {$ELSE} |
46 {$ELSE} |
42 ThinkThread: TThreadID; |
47 ThinkThread: TThreadID; |
43 {$ENDIF} |
48 {$ENDIF} |
44 hasThread: LongInt; |
49 hasThread: LongInt; |
45 StartTicks: Longword; |
50 StartTicks: LongInt; |
46 |
51 |
47 procedure FreeActionsList; |
52 procedure FreeActionsList; |
48 begin |
53 begin |
49 AddFileLog('FreeActionsList called'); |
54 AddFileLog('FreeActionsList called'); |
50 if hasThread <> 0 then |
55 if hasThread <> 0 then |
328 AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0); |
333 AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0); |
329 break |
334 break |
330 end; |
335 end; |
331 |
336 |
332 // 'not CanGO' means we can't go straight, possible jumps are checked above |
337 // 'not CanGO' means we can't go straight, possible jumps are checked above |
333 if not CanGo then |
338 if (not CanGo) then |
334 break; |
339 break; |
335 |
340 |
336 inc(steps); |
341 inc(steps); |
337 Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X); |
342 Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X); |
338 Rate:= RatePlace(Me); |
343 Rate:= RatePlace(Me); |
355 TestAmmos(Actions, Me, ticks shr 12 = oldticks shr 12); |
360 TestAmmos(Actions, Me, ticks shr 12 = oldticks shr 12); |
356 end; |
361 end; |
357 |
362 |
358 if GoInfo.FallPix >= FallPixForBranching then |
363 if GoInfo.FallPix >= FallPixForBranching then |
359 Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right |
364 Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right |
|
365 |
|
366 {$IFDEF AI_MAINTHREAD} |
|
367 if StartTicks < (SDL_GetTicks() - mainThreadMaxThinkTime) then |
|
368 StopThinking := true; |
|
369 {$ELSE} |
|
370 if (StartTicks > GameTicks - 1500) and (not StopThinking) then |
|
371 SDL_Delay(1000); |
|
372 {$ENDIF} |
|
373 |
360 end {while}; |
374 end {while}; |
361 |
375 |
362 if BestRate > BaseRate then |
376 if BestRate > BaseRate then |
363 exit |
377 exit |
364 end {while} |
378 end {while} |
366 end; |
380 end; |
367 |
381 |
368 function Think(Me: Pointer): ptrint; |
382 function Think(Me: Pointer): ptrint; |
369 var BackMe, WalkMe: TGear; |
383 var BackMe, WalkMe: TGear; |
370 switchCount: LongInt; |
384 switchCount: LongInt; |
371 StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i: Longword; |
385 currHedgehogIndex, itHedgehog, switchesNum, i: Longword; |
372 switchImmediatelyAvailable: boolean; |
386 switchImmediatelyAvailable: boolean; |
373 Actions: TActions; |
387 Actions: TActions; |
374 begin |
388 begin |
375 InterlockedIncrement(hasThread); |
389 InterlockedIncrement(hasThread); |
|
390 |
|
391 {$IFDEF AI_MAINTHREAD} |
|
392 StartTicks:= SDL_GetTicks(); |
|
393 {$ELSE} |
376 StartTicks:= GameTicks; |
394 StartTicks:= GameTicks; |
|
395 {$ENDIF} |
|
396 |
377 currHedgehogIndex:= CurrentTeam^.CurrHedgehog; |
397 currHedgehogIndex:= CurrentTeam^.CurrHedgehog; |
378 itHedgehog:= currHedgehogIndex; |
398 itHedgehog:= currHedgehogIndex; |
379 switchesNum:= 0; |
399 switchesNum:= 0; |
380 |
400 |
381 switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher); |
401 switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher); |
382 if PGear(Me)^.Hedgehog^.BotLevel <> 5 then |
402 if PGear(Me)^.Hedgehog^.BotLevel <> 5 then |
383 switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch) |
403 switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch) |
384 else switchCount:= 0; |
404 else switchCount:= 0; |
385 |
405 |
386 if (PGear(Me)^.State and gstAttacked) = 0 then |
406 if (PGear(Me)^.State and gstAttacking) = 0 then |
387 if Targets.Count > 0 then |
407 if Targets.Count > 0 then |
388 begin |
408 begin |
389 // iterate over current team hedgehogs |
409 // iterate over current team hedgehogs |
390 repeat |
410 repeat |
391 WalkMe:= CurrentTeam^.Hedgehogs[itHedgehog].Gear^; |
411 WalkMe:= CurrentTeam^.Hedgehogs[itHedgehog].Gear^; |
393 Actions.Count:= 0; |
413 Actions.Count:= 0; |
394 Actions.Pos:= 0; |
414 Actions.Pos:= 0; |
395 Actions.Score:= 0; |
415 Actions.Score:= 0; |
396 if switchesNum > 0 then |
416 if switchesNum > 0 then |
397 begin |
417 begin |
398 if not switchImmediatelyAvailable then |
418 if (not switchImmediatelyAvailable) then |
399 begin |
419 begin |
400 // when AI has to use switcher, make it cost smth unless they have a lot of switches |
420 // when AI has to use switcher, make it cost smth unless they have a lot of switches |
401 if (switchCount < 10) then Actions.Score:= (-27+switchCount*3)*4000; |
421 if (switchCount < 10) then Actions.Score:= (-27+switchCount*3)*4000; |
402 AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0); |
422 AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0); |
403 AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0); |
423 AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0); |
418 until (not (switchImmediatelyAvailable or (switchCount > 0))) |
438 until (not (switchImmediatelyAvailable or (switchCount > 0))) |
419 or StopThinking |
439 or StopThinking |
420 or (itHedgehog = currHedgehogIndex) |
440 or (itHedgehog = currHedgehogIndex) |
421 or BestActions.isWalkingToABetterPlace; |
441 or BestActions.isWalkingToABetterPlace; |
422 |
442 |
423 if (StartTicks > GameTicks - 1500) and (not StopThinking) then |
443 {$IFDEF AI_MAINTHREAD} |
424 SDL_Delay(1000); |
444 if StartTicks < (SDL_GetTicks() - mainThreadMaxThinkTime) then |
|
445 StopThinking := true; |
|
446 {$ELSE} |
|
447 if (StartTicks > GameTicks - 1500) and (not StopThinking) then |
|
448 SDL_Delay(1000); |
|
449 {$ENDIF} |
425 |
450 |
426 if (BestActions.Score < -1023) and (not BestActions.isWalkingToABetterPlace) then |
451 if (BestActions.Score < -1023) and (not BestActions.isWalkingToABetterPlace) then |
427 begin |
452 begin |
428 BestActions.Count:= 0; |
453 BestActions.Count:= 0; |
429 AddAction(BestActions, aia_Skip, 0, 250, 0, 0); |
454 AddAction(BestActions, aia_Skip, 0, 250, 0, 0); |
431 |
456 |
432 end else |
457 end else |
433 else |
458 else |
434 begin |
459 begin |
435 BackMe:= PGear(Me)^; |
460 BackMe:= PGear(Me)^; |
|
461 |
|
462 //{$IFNDEF AI_MAINTHREAD} |
436 while (not StopThinking) and (BestActions.Count = 0) do |
463 while (not StopThinking) and (BestActions.Count = 0) do |
437 begin |
464 begin |
|
465 |
438 (* |
466 (* |
439 // 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 |
467 // 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 |
440 if SuddenDeathDmg and ((hwRound(BackMe.Y)+cWaterRise*2) > cWaterLine) then |
468 if SuddenDeathDmg and ((hwRound(BackMe.Y)+cWaterRise*2) > cWaterLine) then |
441 AddBonus(hwRound(BackMe.X), hwRound(BackMe.Y), 250, -40); |
469 AddBonus(hwRound(BackMe.X), hwRound(BackMe.Y), 250, -40); |
442 *) |
470 *) |
|
471 |
443 FillBonuses(true); |
472 FillBonuses(true); |
444 WalkMe:= BackMe; |
473 WalkMe:= BackMe; |
445 Actions.Count:= 0; |
474 Actions.Count:= 0; |
446 Actions.Pos:= 0; |
475 Actions.Pos:= 0; |
447 Actions.Score:= 0; |
476 Actions.Score:= 0; |
448 Walk(@WalkMe, Actions); |
477 Walk(@WalkMe, Actions); |
449 if not StopThinking then |
478 {$IFNDEF AI_MAINTHREAD} |
|
479 if (not StopThinking) then |
450 SDL_Delay(100) |
480 SDL_Delay(100) |
|
481 {$ENDIF} |
451 end |
482 end |
|
483 //{$ENDIF} |
452 end; |
484 end; |
453 |
485 |
454 PGear(Me)^.State:= PGear(Me)^.State and (not gstHHThinking); |
486 PGear(Me)^.State:= PGear(Me)^.State and (not gstHHThinking); |
455 Think:= 0; |
487 Think:= 0; |
456 InterlockedDecrement(hasThread) |
488 InterlockedDecrement(hasThread) |
482 exit |
514 exit |
483 end; |
515 end; |
484 |
516 |
485 FillBonuses((Me^.State and gstAttacked) <> 0); |
517 FillBonuses((Me^.State and gstAttacked) <> 0); |
486 AddFileLog('Enter Think Thread'); |
518 AddFileLog('Enter Think Thread'); |
|
519 |
|
520 {$IFDEF AI_MAINTHREAD} |
|
521 Think(Me); |
|
522 {$ELSE} |
487 {$IFDEF USE_SDLTHREADS} |
523 {$IFDEF USE_SDLTHREADS} |
488 ThinkThread := SDL_CreateThread(@Think{$IFDEF SDL13}, nil{$ENDIF}, Me); |
524 ThinkThread := SDL_CreateThread(@Think{$IFDEF SDL13}, nil{$ENDIF}, Me); |
489 {$ELSE} |
525 {$ELSE} |
490 BeginThread(@Think, Me, ThinkThread); |
526 BeginThread(@Think, Me, ThinkThread); |
491 {$ENDIF} |
527 {$ENDIF} |
492 AddFileLog('Thread started'); |
528 AddFileLog('Thread started'); |
|
529 {$ENDIF} |
493 end; |
530 end; |
494 |
531 |
495 //var scoreShown: boolean = false; |
532 //var scoreShown: boolean = false; |
496 |
533 |
497 procedure ProcessBot; |
534 procedure ProcessBot; |