diff -r fc52f7c22c9b -r 6155187bf599 hedgewars/uAI.pas --- a/hedgewars/uAI.pas Mon Jan 16 10:22:21 2012 +0100 +++ b/hedgewars/uAI.pas Tue Jan 17 09:01:31 2012 -0500 @@ -30,8 +30,8 @@ implementation uses uConsts, SDLh, uAIMisc, uAIAmmoTests, uAIActions, - uAmmos, SysUtils{$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF}, uTypes, - uVariables, uCommands, uUtils, uDebug; + uAmmos, SysUtils{$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF}, uTypes, + uVariables, uCommands, uUtils, uDebug; var BestActions: TActions; CanUseAmmo: array [TAmmoType] of boolean; @@ -47,18 +47,18 @@ begin AddFileLog('FreeActionsList called'); if hasThread <> 0 then - begin - AddFileLog('Waiting AI thread to finish'); - StopThinking:= true; - repeat - SDL_Delay(10) - until hasThread = 0 - end; + begin + AddFileLog('Waiting AI thread to finish'); + StopThinking:= true; + repeat + SDL_Delay(10) + until hasThread = 0 + end; with CurrentHedgehog^ do - if Gear <> nil then + if Gear <> nil then if BotLevel <> 0 then - StopMessages(Gear^.Message); + StopMessages(Gear^.Message); BestActions.Count:= 0; BestActions.Pos:= 0 @@ -117,66 +117,71 @@ for i:= 0 to Pred(Targets.Count) do if (Targets.ar[i].Score >= 0) and (not StopThinking) then - begin - with CurrentHedgehog^ do + begin + with CurrentHedgehog^ do a:= CurAmmoType; - aa:= a; + aa:= a; {$IFDEF USE_SDLTHREADS} - SDL_delay(0); //ThreadSwitch was only a hint + SDL_delay(0); //ThreadSwitch was only a hint {$ELSE} - ThreadSwitch(); + ThreadSwitch(); {$ENDIF} - repeat + repeat if (CanUseAmmo[a]) and - ((not isMoved) or ((AmmoTests[a].flags and amtest_OnTurn) = 0)) then - begin + ((not isMoved) or ((AmmoTests[a].flags and amtest_OnTurn) = 0)) then + begin {$HINTS OFF} - Score:= AmmoTests[a].proc(Me, Targets.ar[i].Point, BotLevel, ap); + Score:= AmmoTests[a].proc(Me, Targets.ar[i].Point, BotLevel, ap); {$HINTS ON} - if Actions.Score + Score > BestActions.Score then - if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + Byte(BotLevel) * 2048) then - begin - BestActions:= Actions; - inc(BestActions.Score, Score); - BestActions.isWalkingToABetterPlace:= false; + if Actions.Score + Score > BestActions.Score then + if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + Byte(BotLevel) * 2048) then + begin + BestActions:= Actions; + inc(BestActions.Score, Score); + BestActions.isWalkingToABetterPlace:= false; - if (ap.Angle > 0) then AddAction(BestActions, aia_LookRight, 0, 200, 0, 0) - else if (ap.Angle < 0) then AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0); + if (ap.Angle > 0) then + AddAction(BestActions, aia_LookRight, 0, 200, 0, 0) + else if (ap.Angle < 0) then + AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0); - AddAction(BestActions, aia_Weapon, Longword(a), 300 + random(400), 0, 0); - if (ap.Time <> 0) then AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0); - if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then - begin - ap.Angle:= LongInt(Me^.Angle) - Abs(ap.Angle); - if ap.Angle > 0 then - begin - AddAction(BestActions, aia_Up, aim_push, 300 + random(250), 0, 0); - AddAction(BestActions, aia_Up, aim_release, ap.Angle, 0, 0) - end else if ap.Angle < 0 then + AddAction(BestActions, aia_Weapon, Longword(a), 300 + random(400), 0, 0); + + if (ap.Time <> 0) then + AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0); + if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then begin - AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0); - AddAction(BestActions, aia_Down, aim_release, -ap.Angle, 0, 0) - end - end; - if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then - begin - AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY) - end; - if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then - begin - AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0); - AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0); - end; - if ap.ExplR > 0 then - AddAction(BestActions, aia_AwareExpl, ap.ExplR, 10, ap.ExplX, ap.ExplY); - end - end; - if a = High(TAmmoType) then a:= Low(TAmmoType) - else inc(a) - until (a = aa) or - (CurrentHedgehog^.MultiShootAttacks > 0) or // shooting same weapon - StopThinking - end + ap.Angle:= LongInt(Me^.Angle) - Abs(ap.Angle); + if ap.Angle > 0 then + begin + AddAction(BestActions, aia_Up, aim_push, 300 + random(250), 0, 0); + AddAction(BestActions, aia_Up, aim_release, ap.Angle, 0, 0) + end + else if ap.Angle < 0 then + begin + AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0); + AddAction(BestActions, aia_Down, aim_release, -ap.Angle, 0, 0) + end + end; + if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then + begin + AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY) + end; + if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then + begin + AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0); + AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0); + end; + if ap.ExplR > 0 then + AddAction(BestActions, aia_AwareExpl, ap.ExplR, 10, ap.ExplX, ap.ExplY); + end + end; + if a = High(TAmmoType) then + a:= Low(TAmmoType) + else inc(a) + until (a = aa) or (CurrentHedgehog^.MultiShootAttacks > 0) or // shooting same weapon + StopThinking + end end; procedure Walk(Me: PGear; var Actions: TActions); @@ -202,10 +207,14 @@ Push(0, Actions, Me^, tmp); Push(0, Actions, Me^, tmp xor 3); -if (Me^.State and gstAttacked) = 0 then maxticks:= Max(0, TurnTimeLeft - 5000 - LongWord(4000 * BotLevel)) - else maxticks:= TurnTimeLeft; +if (Me^.State and gstAttacked) = 0 then + maxticks:= Max(0, TurnTimeLeft - 5000 - LongWord(4000 * BotLevel)) +else + maxticks:= TurnTimeLeft; -if (Me^.State and gstAttacked) = 0 then TestAmmos(Actions, Me, false); +if (Me^.State and gstAttacked) = 0 then + TestAmmos(Actions, Me, false); + BestRate:= RatePlace(Me); BaseRate:= Max(BestRate, 0); @@ -217,54 +226,67 @@ Pop(ticks, Actions, Me^); AddAction(Actions, Me^.Message, aim_push, 250, 0, 0); - if (Me^.Message and gmLeft) <> 0 then AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0) - else AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0); + if (Me^.Message and gmLeft) <> 0 then + AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0) + else + AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0); + steps:= 0; while (not StopThinking) do - begin + begin {$HINTS OFF} - CanGo:= HHGo(Me, @AltMe, GoInfo); + CanGo:= HHGo(Me, @AltMe, GoInfo); {$HINTS ON} - inc(ticks, GoInfo.Ticks); - if ticks > maxticks then break; + inc(ticks, GoInfo.Ticks); + if ticks > maxticks then + break; - if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support - if Push(ticks, Actions, AltMe, Me^.Message) then - with Stack.States[Pred(Stack.Count)] do - begin - if Me^.dX.isNegative then AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0) - else AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0); - AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0); - AddAction(MadeActions, aia_HJump, 0, 350, 0, 0); - if Me^.dX.isNegative then AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0) - else AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0); - end; - if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support - if Push(ticks, Actions, AltMe, Me^.Message) then - with Stack.States[Pred(Stack.Count)] do - AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0); + if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support + if Push(ticks, Actions, AltMe, Me^.Message) then + with Stack.States[Pred(Stack.Count)] do + begin + if Me^.dX.isNegative then + AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0) + else + AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0); + + AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0); + AddAction(MadeActions, aia_HJump, 0, 350, 0, 0); + + if Me^.dX.isNegative then + AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0) + else + AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0); + end; + if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support + if Push(ticks, Actions, AltMe, Me^.Message) then + with Stack.States[Pred(Stack.Count)] do + AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0); - if not CanGo then break; - inc(steps); - Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X); - Rate:= RatePlace(Me); - if Rate > BestRate then - begin - BestActions:= Actions; - BestActions.isWalkingToABetterPlace:= true; - BestRate:= Rate; - Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo - end - else if Rate < BestRate then break; - if ((Me^.State and gstAttacked) = 0) - and ((steps mod 4) = 0) then TestAmmos(Actions, Me, true); - if GoInfo.FallPix >= FallPixForBranching then - Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right - end; + if not CanGo then + break; + inc(steps); + Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X); + Rate:= RatePlace(Me); + if Rate > BestRate then + begin + BestActions:= Actions; + BestActions.isWalkingToABetterPlace:= true; + BestRate:= Rate; + Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo + end + else if Rate < BestRate then + break; + if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then + TestAmmos(Actions, Me, true); + if GoInfo.FallPix >= FallPixForBranching then + Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right + end; - if BestRate > BaseRate then exit - end + if BestRate > BaseRate then + exit + end end; function Think(Me: Pointer): ptrint; @@ -283,8 +305,8 @@ switchAvailable:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch); if (PGear(Me)^.State and gstAttacked) = 0 then - if Targets.Count > 0 then - begin + if Targets.Count > 0 then + begin // iterate over current team hedgehogs repeat WalkMe:= CurrentTeam^.Hedgehogs[itHedgehog].Gear^; @@ -318,7 +340,8 @@ or (itHedgehog = currHedgehogIndex) or BestActions.isWalkingToABetterPlace; - if (StartTicks > GameTicks - 1500) and (not StopThinking) then SDL_Delay(1000); + if (StartTicks > GameTicks - 1500) and (not StopThinking) then + SDL_Delay(1000); if (BestActions.Score < -1023) and (not BestActions.isWalkingToABetterPlace) then begin @@ -326,8 +349,9 @@ AddAction(BestActions, aia_Skip, 0, 250, 0, 0); end; - end else -else begin + end else +else + begin BackMe:= PGear(Me)^; while (not StopThinking) and (BestActions.Count = 0) do begin @@ -337,7 +361,8 @@ Actions.Pos:= 0; Actions.Score:= 0; Walk(@WalkMe, Actions); - if not StopThinking then SDL_Delay(100) + if not StopThinking then + SDL_Delay(100) end end; @@ -349,7 +374,8 @@ procedure StartThink(Me: PGear); begin if ((Me^.State and (gstAttacking or gstHHJumping or gstMoving)) <> 0) - or isInMultiShoot then exit; +or isInMultiShoot then + exit; //DeleteCI(Me); // this might break demo Me^.State:= Me^.State or gstHHThinking; @@ -365,10 +391,10 @@ FillTargets; if Targets.Count = 0 then - begin - OutError('AI: no targets!?', false); - exit - end; + begin + OutError('AI: no targets!?', false); + exit + end; FillBonuses((Me^.State and gstAttacked) <> 0); AddFileLog('Enter Think Thread'); @@ -385,24 +411,28 @@ cStopThinkTime = 40; begin with CurrentHedgehog^ do - if (Gear <> nil) - and ((Gear^.State and gstHHDriven) <> 0) - and (TurnTimeLeft < cHedgehogTurnTime - 50) then + if (Gear <> nil) + and ((Gear^.State and gstHHDriven) <> 0) + and (TurnTimeLeft < cHedgehogTurnTime - 50) then if ((Gear^.State and gstHHThinking) = 0) then - if (BestActions.Pos >= BestActions.Count) - and (TurnTimeLeft > cStopThinkTime) then - begin - if Gear^.Message <> 0 then - begin - StopMessages(Gear^.Message); - TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true); - end; - if Gear^.Message <> 0 then exit; - StartThink(Gear); - StartTicks:= GameTicks - end else ProcessAction(BestActions, Gear) + if (BestActions.Pos >= BestActions.Count) + and (TurnTimeLeft > cStopThinkTime) then + begin + if Gear^.Message <> 0 then + begin + StopMessages(Gear^.Message); + TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true); + end; + if Gear^.Message <> 0 then + exit; + StartThink(Gear); + StartTicks:= GameTicks + + end else + ProcessAction(BestActions, Gear) else if ((GameTicks - StartTicks) > cMaxAIThinkTime) - or (TurnTimeLeft <= cStopThinkTime) then StopThinking:= true + or (TurnTimeLeft <= cStopThinkTime) then + StopThinking:= true end; procedure initModule;