41 uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc; |
41 uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc; |
42 |
42 |
43 var BestActions: TActions; |
43 var BestActions: TActions; |
44 ThinkThread: PSDL_Thread = nil; |
44 ThinkThread: PSDL_Thread = nil; |
45 StopThinking: boolean; |
45 StopThinking: boolean; |
|
46 CanUseAmmo: array [TAmmoType] of boolean; |
46 |
47 |
47 procedure FreeActionsList; |
48 procedure FreeActionsList; |
48 begin |
49 begin |
49 if ThinkThread <> nil then |
50 if ThinkThread <> nil then |
50 begin |
51 begin |
63 a, aa: TAmmoType; |
64 a, aa: TAmmoType; |
64 begin |
65 begin |
65 for i:= 0 to Pred(Targets.Count) do |
66 for i:= 0 to Pred(Targets.Count) do |
66 if Targets.ar[i].Score >= 0 then |
67 if Targets.ar[i].Score >= 0 then |
67 begin |
68 begin |
68 if (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0) |
69 with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do |
69 then with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do |
70 a:= Ammo[CurSlot, CurAmmo].AmmoType; |
70 a:= Ammo[CurSlot, CurAmmo].AmmoType |
|
71 else a:= Low(TAmmoType); |
|
72 aa:= a; |
71 aa:= a; |
73 repeat |
72 repeat |
74 if Assigned(AmmoTests[a]) then |
73 if CanUseAmmo[a] then |
75 begin |
74 begin |
76 Score:= AmmoTests[a](Me, Targets.ar[i].Point, Time, Angle, Power, ExplX, ExplY, ExplR); |
75 Score:= AmmoTests[a](Me, Targets.ar[i].Point, Time, Angle, Power, ExplX, ExplY, ExplR); |
77 if Actions.Score + Score + Targets.ar[i].Score > BestActions.Score then |
76 if Actions.Score + Score + Targets.ar[i].Score > BestActions.Score then |
78 begin |
77 begin |
79 BestActions:= Actions; |
78 BestActions:= Actions; |
103 until (a = aa) or (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0) |
102 until (a = aa) or (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0) |
104 end |
103 end |
105 end; |
104 end; |
106 |
105 |
107 procedure Walk(Me: PGear); |
106 procedure Walk(Me: PGear); |
|
107 const FallTicksForBranching = cHHRadius * 2 + 8; |
|
108 cBranchStackSize = 8; |
|
109 |
|
110 type TStackEntry = record |
|
111 WastedTicks: Longword; |
|
112 MadeActions: TActions; |
|
113 Hedgehog: TGear; |
|
114 end; |
|
115 |
|
116 var Stack: record |
|
117 Count: Longword; |
|
118 States: array[0..Pred(cBranchStackSize)] of TStackEntry; |
|
119 end; |
|
120 |
|
121 procedure Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer); |
|
122 begin |
|
123 if Stack.Count < cBranchStackSize then |
|
124 with Stack.States[Stack.Count] do |
|
125 begin |
|
126 WastedTicks:= Ticks; |
|
127 MadeActions:= Actions; |
|
128 Hedgehog:= Me; |
|
129 Hedgehog.Message:= Dir; |
|
130 inc(Stack.Count) |
|
131 end |
|
132 end; |
|
133 |
|
134 procedure Pop(out Ticks: Longword; out Actions: TActions; out Me: TGear); |
|
135 begin |
|
136 dec(Stack.Count); |
|
137 with Stack.States[Stack.Count] do |
|
138 begin |
|
139 Ticks:= WastedTicks; |
|
140 Actions:= MadeActions; |
|
141 Me:= Hedgehog |
|
142 end |
|
143 end; |
|
144 |
|
145 |
108 var Actions: TActions; |
146 var Actions: TActions; |
109 BackMe: TGear; |
147 ticks, maxticks, steps: Longword; |
110 Dir, steps, maxsteps: integer; |
148 BaseRate, BestRate, Rate: integer; |
111 BestRate, Rate: integer; |
149 GoInfo: TGoInfo; |
112 begin |
150 begin |
113 Actions.Score:= 0; |
|
114 Actions.Count:= 0; |
151 Actions.Count:= 0; |
115 Actions.Pos:= 0; |
152 Actions.Pos:= 0; |
116 BestActions.Count:= 0; |
153 Actions.Score:= 0; |
117 if (Me.State and gstAttacked) = 0 then maxsteps:= (TurnTimeLeft - 4000) div cHHStepTicks |
154 Stack.Count:= 0; |
118 else maxsteps:= TurnTimeLeft div cHHStepTicks; |
155 |
119 BackMe:= Me^; |
156 Push(0, Actions, Me^, aia_Left); |
|
157 Push(0, Actions, Me^, aia_Right); |
|
158 |
|
159 if (Me.State and gstAttacked) = 0 then maxticks:= TurnTimeLeft - 5000 |
|
160 else maxticks:= TurnTimeLeft; |
|
161 |
120 if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me); |
162 if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me); |
121 BestRate:= RatePlace(Me); |
163 BestRate:= RatePlace(Me); |
122 for Dir:= aia_Left to aia_Right do |
164 BaseRate:= max(BestRate, 0); |
|
165 |
|
166 while (Stack.Count > 0) and not StopThinking do |
123 begin |
167 begin |
124 Me.Message:= Dir; |
168 Pop(ticks, Actions, Me^); |
|
169 AddAction(Actions, Me.Message, aim_push, 250); |
|
170 AddAction(Actions, aia_WaitX, round(Me.X), 0); |
|
171 AddAction(Actions, Me.Message, aim_release, 0); |
125 steps:= 0; |
172 steps:= 0; |
126 while HHGo(Me) and (steps < maxsteps) do |
173 |
|
174 while HHGo(Me, GoInfo) do |
127 begin |
175 begin |
|
176 inc(ticks, GoInfo.Ticks); |
|
177 if ticks > maxticks then break; |
128 inc(steps); |
178 inc(steps); |
129 Actions.Count:= 0; |
179 Actions.actions[Actions.Count - 2].Param:= round(Me.X); |
130 AddAction(Actions, Dir, aim_push, 250); |
|
131 AddAction(Actions, aia_WaitX, round(Me.X), 0); |
|
132 AddAction(Actions, Dir, aim_release, 0); |
|
133 Rate:= RatePlace(Me); |
180 Rate:= RatePlace(Me); |
134 if Rate > BestRate then |
181 if Rate > BestRate then |
135 begin |
182 begin |
136 BestActions:= Actions; |
183 BestActions:= Actions; |
137 BestRate:= Rate; |
184 BestRate:= Rate; |
138 Me.State:= Me.State or gstAttacked // we have better place, go there and don't use ammo |
185 Me.State:= Me.State or gstAttacked // we have better place, go there and don't use ammo |
139 end |
186 end |
140 else if Rate < BestRate then |
187 else if Rate < BestRate then break; |
141 if BestRate > 0 then exit |
|
142 else break; |
|
143 if ((Me.State and gstAttacked) = 0) |
188 if ((Me.State and gstAttacked) = 0) |
144 and ((steps mod 4) = 0) then TestAmmos(Actions, Me); |
189 and ((steps mod 4) = 0) then TestAmmos(Actions, Me); |
145 if StopThinking then exit; |
190 if GoInfo.FallTicks >= FallTicksForBranching then |
|
191 Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right |
|
192 if StopThinking then exit |
146 end; |
193 end; |
147 Me^:= BackMe |
194 |
|
195 if BestRate > BaseRate then exit |
148 end |
196 end |
149 end; |
197 end; |
150 |
198 |
151 procedure Think(Me: PGear); cdecl; |
199 procedure Think(Me: PGear); cdecl; |
152 var BackMe, WalkMe: TGear; |
200 var BackMe, WalkMe: TGear; |
170 begin |
218 begin |
171 SDL_Delay(100); |
219 SDL_Delay(100); |
172 FillBonuses(true); |
220 FillBonuses(true); |
173 WalkMe:= BackMe; |
221 WalkMe:= BackMe; |
174 Walk(@WalkMe) |
222 Walk(@WalkMe) |
175 end; |
223 end |
176 AwareOfExplosion(0, 0, 0) |
|
177 end; |
224 end; |
178 |
225 |
179 Me.State:= Me.State and not gstHHThinking; |
226 Me.State:= Me.State and not gstHHThinking; |
180 ThinkThread:= nil |
227 ThinkThread:= nil |
181 end; |
228 end; |
182 |
229 |
183 procedure StartThink(Me: PGear); |
230 procedure StartThink(Me: PGear); |
|
231 var a: TAmmoType; |
184 begin |
232 begin |
185 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit; |
233 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit; |
186 Me.State:= Me.State or gstHHThinking; |
234 Me.State:= Me.State or gstHHThinking; |
187 StopThinking:= false; |
235 StopThinking:= false; |
188 ThinkingHH:= Me; |
236 ThinkingHH:= Me; |
189 FillTargets; |
237 FillTargets; |
190 FillBonuses((Me.State and gstAttacked) <> 0); |
238 FillBonuses((Me.State and gstAttacked) <> 0); |
|
239 for a:= Low(TAmmoType) to High(TAmmoType) do |
|
240 CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me.Hedgehog), a); |
191 {$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF} |
241 {$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF} |
192 ThinkThread:= SDL_CreateThread(@Think, Me) |
242 ThinkThread:= SDL_CreateThread(@Think, Me) |
193 end; |
243 end; |
194 |
244 |
195 procedure ProcessBot; |
245 procedure ProcessBot; |