90 AddAction(BestActions, aia_AwareExpl, ExplR, 10, ExplX, ExplY); |
84 AddAction(BestActions, aia_AwareExpl, ExplR, 10, ExplX, ExplY); |
91 end |
85 end |
92 end; |
86 end; |
93 if a = High(TAmmoType) then a:= Low(TAmmoType) |
87 if a = High(TAmmoType) then a:= Low(TAmmoType) |
94 else inc(a) |
88 else inc(a) |
95 until (a = aa) or (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0) |
89 until (a = aa) or (PHedgehog(Me.Hedgehog).AttacksNum > 0) |
96 end |
90 end |
97 end; |
91 end; |
98 |
92 |
99 procedure Walk(Me: PGear); |
93 procedure Walk(Me: PGear); |
100 const FallPixForBranching = cHHRadius * 2 + 8; |
94 const FallPixForBranching = cHHRadius * 2 + 8; |
101 cBranchStackSize = 12; |
|
102 |
95 |
103 type TStackEntry = record |
|
104 WastedTicks: Longword; |
|
105 MadeActions: TActions; |
|
106 Hedgehog: TGear; |
|
107 end; |
|
108 |
|
109 var Stack: record |
|
110 Count: Longword; |
|
111 States: array[0..Pred(cBranchStackSize)] of TStackEntry; |
|
112 end; |
|
113 |
|
114 function Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer): boolean; |
|
115 begin |
|
116 Result:= (Stack.Count < cBranchStackSize) and (Actions.Count < MAXACTIONS - 5); |
|
117 if Result then |
|
118 with Stack.States[Stack.Count] do |
|
119 begin |
|
120 WastedTicks:= Ticks; |
|
121 MadeActions:= Actions; |
|
122 Hedgehog:= Me; |
|
123 Hedgehog.Message:= Dir; |
|
124 inc(Stack.Count) |
|
125 end |
|
126 end; |
|
127 |
|
128 procedure Pop(out Ticks: Longword; out Actions: TActions; out Me: TGear); |
|
129 begin |
|
130 dec(Stack.Count); |
|
131 with Stack.States[Stack.Count] do |
|
132 begin |
|
133 Ticks:= WastedTicks; |
|
134 Actions:= MadeActions; |
|
135 Me:= Hedgehog |
|
136 end |
|
137 end; |
|
138 |
|
139 function PosInThinkStack(Me: PGear): boolean; |
|
140 var i: Longword; |
|
141 begin |
|
142 i:= 0; |
|
143 Result:= false; |
|
144 while (i < Stack.Count) and not Result do |
|
145 begin |
|
146 Result:= (abs(Stack.States[i].Hedgehog.X - Me.X) + |
|
147 abs(Stack.States[i].Hedgehog.Y - Me.Y) <= 2) |
|
148 and (Stack.States[i].Hedgehog.Message = Me.Message); |
|
149 inc(i) |
|
150 end |
|
151 end; |
|
152 |
|
153 |
|
154 var Actions: TActions; |
96 var Actions: TActions; |
155 ticks, maxticks, steps, BotLevel, tmp: Longword; |
97 ticks, maxticks, steps, BotLevel: Longword; |
156 BaseRate, BestRate, Rate: integer; |
98 BaseRate, Rate: integer; |
157 GoInfo: TGoInfo; |
99 GoInfo: TGoInfo; |
158 CanGo: boolean; |
100 CanGo: boolean; |
159 AltMe: TGear; |
101 AltMe: TGear; |
160 begin |
102 begin |
161 Actions.Count:= 0; |
|
162 Actions.Pos:= 0; |
|
163 Actions.Score:= 0; |
|
164 Stack.Count:= 0; |
|
165 BotLevel:= PHedgehog(Me.Hedgehog).BotLevel; |
103 BotLevel:= PHedgehog(Me.Hedgehog).BotLevel; |
166 |
|
167 tmp:= random(2) + 1; |
|
168 Push(0, Actions, Me^, tmp); |
|
169 Push(0, Actions, Me^, tmp xor 3); |
|
170 |
104 |
171 if (Me.State and gstAttacked) = 0 then maxticks:= max(0, TurnTimeLeft - 5000 - 4000 * BotLevel) |
105 if (Me.State and gstAttacked) = 0 then maxticks:= max(0, TurnTimeLeft - 5000 - 4000 * BotLevel) |
172 else maxticks:= TurnTimeLeft; |
106 else maxticks:= TurnTimeLeft; |
173 |
107 |
174 if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me); |
108 |
175 BestRate:= RatePlace(Me); |
109 BaseRate:= max(RatePlace(Me), 0); |
176 BaseRate:= max(BestRate, 0); |
110 |
177 |
111 repeat |
178 while (Stack.Count > 0) and not StopThinking do |
112 if not Pop(ticks, Actions, Me^) then |
179 begin |
113 begin |
180 Pop(ticks, Actions, Me^); |
114 isThinking:= false; |
181 |
115 exit |
|
116 end; |
182 AddAction(Actions, Me.Message, aim_push, 250); |
117 AddAction(Actions, Me.Message, aim_push, 250); |
183 AddAction(Actions, aia_WaitX, round(Me.X), 0); |
118 AddAction(Actions, aia_WaitX, round(Me.X), 0); |
184 AddAction(Actions, Me.Message, aim_release, 0); |
119 AddAction(Actions, Me.Message, aim_release, 0); |
185 steps:= 0; |
120 steps:= 0; |
186 |
121 |
187 while (not StopThinking) and (not PosInThinkStack(Me)) do |
122 while not PosInThinkStack(Me) do |
188 begin |
123 begin |
|
124 if SDL_GetTicks - AIThinkStart > 3 then |
|
125 begin |
|
126 writetoconsole(inttostr(SDL_GetTicks - AIThinkStart) + ' '); |
|
127 dec(Actions.Count, 3); |
|
128 Push(ticks, Actions, Me^, Me^.Message); |
|
129 exit |
|
130 end; |
|
131 |
189 CanGo:= HHGo(Me, @AltMe, GoInfo); |
132 CanGo:= HHGo(Me, @AltMe, GoInfo); |
190 inc(ticks, GoInfo.Ticks); |
133 inc(ticks, GoInfo.Ticks); |
191 if ticks > maxticks then break; |
134 if ticks > maxticks then break; |
192 |
135 |
193 if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support |
136 if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support |
194 if Push(ticks, Actions, AltMe, Me^.Message) then |
137 if Push(ticks, Actions, AltMe, Me^.Message) then |
195 with Stack.States[Pred(Stack.Count)] do |
138 with ThinkStack.States[Pred(ThinkStack.Count)] do |
196 begin |
139 begin |
197 AddAction(MadeActions, aia_HJump, 0, 305); |
140 AddAction(MadeActions, aia_HJump, 0, 305); |
198 AddAction(MadeActions, aia_HJump, 0, 350); |
141 AddAction(MadeActions, aia_HJump, 0, 350); |
199 end; |
142 end; |
200 if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support |
143 if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support |
201 if Push(ticks, Actions, AltMe, Me^.Message) then |
144 if Push(ticks, Actions, AltMe, Me^.Message) then |
202 with Stack.States[Pred(Stack.Count)] do |
145 with ThinkStack.States[Pred(ThinkStack.Count)] do |
203 AddAction(MadeActions, aia_LJump, 0, 305); |
146 AddAction(MadeActions, aia_LJump, 0, 305); |
204 |
147 |
205 if not CanGo then break; |
148 if not CanGo then break; |
206 inc(steps); |
149 inc(steps); |
207 Actions.actions[Actions.Count - 2].Param:= round(Me.X); |
150 Actions.actions[Actions.Count - 2].Param:= round(Me.X); |
208 Rate:= RatePlace(Me); |
151 Rate:= RatePlace(Me); |
209 if Rate > BestRate then |
152 if Rate > BaseRate then |
210 begin |
153 begin |
211 BestActions:= Actions; |
154 BestActions:= Actions; |
212 BestRate:= Rate; |
155 BestActions.Score:= 1; |
213 Me.State:= Me.State or gstAttacked // we have better place, go there and don't use ammo |
156 isThinking:= false; |
|
157 exit |
214 end |
158 end |
215 else if Rate < BestRate then break; |
159 else if Rate < BaseRate then break; |
216 if ((Me.State and gstAttacked) = 0) |
160 if ((Me.State and gstAttacked) = 0) |
217 and ((steps mod 4) = 0) then TestAmmos(Actions, Me); |
161 and ((steps mod 4) = 0) then TestAmmos(Actions, Me); |
218 if GoInfo.FallPix >= FallPixForBranching then |
162 if GoInfo.FallPix >= FallPixForBranching then |
219 Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right |
163 Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right |
220 end; |
164 end; |
221 |
165 until false |
222 if BestRate > BaseRate then exit |
166 end; |
223 end |
167 |
224 end; |
168 procedure Think(Me: PGear); |
225 |
|
226 procedure Think(Me: PGear); cdecl; |
|
227 var BackMe, WalkMe: TGear; |
169 var BackMe, WalkMe: TGear; |
228 StartTicks: Longword; |
170 // StartTicks: Longword; |
229 begin |
171 begin |
230 StartTicks:= GameTicks; |
172 AIThinkStart:= SDL_GetTicks; |
231 BestActions.Count:= 0; |
|
232 BestActions.Pos:= 0; |
|
233 BestActions.Score:= Low(integer); |
|
234 BackMe:= Me^; |
173 BackMe:= Me^; |
235 WalkMe:= BackMe; |
174 WalkMe:= BackMe; |
236 if (Me.State and gstAttacked) = 0 then |
175 if (Me.State and gstAttacked) = 0 then |
237 if Targets.Count > 0 then |
176 if Targets.Count > 0 then |
238 begin |
177 begin |
239 Walk(@WalkMe); |
178 Walk(@WalkMe); |
240 if (StartTicks > GameTicks - 1500) and not StopThinking then SDL_Delay(2000); |
179 if not isThinking then |
241 if BestActions.Score < -1023 then |
|
242 begin |
180 begin |
243 BestActions.Count:= 0; |
181 if BestActions.Score < -1023 then |
244 AddAction(BestActions, aia_Skip, 0, 250); |
182 begin |
245 end; |
183 BestActions.Count:= 0; |
|
184 AddAction(BestActions, aia_Skip, 0, 250); |
|
185 end; |
|
186 Me.State:= Me.State and not gstHHThinking |
|
187 end |
246 end else |
188 end else |
247 else begin |
189 else begin |
248 Walk(@WalkMe); |
190 FillBonuses(true); |
249 while (not StopThinking) and (BestActions.Count = 0) do |
191 Walk(@WalkMe) |
250 begin |
192 end |
251 SDL_Delay(100); |
|
252 FillBonuses(true); |
|
253 WalkMe:= BackMe; |
|
254 Walk(@WalkMe) |
|
255 end |
|
256 end; |
|
257 Me.State:= Me.State and not gstHHThinking |
|
258 end; |
193 end; |
259 |
194 |
260 procedure StartThink(Me: PGear); |
195 procedure StartThink(Me: PGear); |
261 var a: TAmmoType; |
196 var a: TAmmoType; |
|
197 tmp: integer; |
262 begin |
198 begin |
263 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit; |
199 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit; |
|
200 ThinkingHH:= Me; |
|
201 isThinking:= true; |
|
202 |
|
203 ClearThinkStack; |
|
204 |
264 Me.State:= Me.State or gstHHThinking; |
205 Me.State:= Me.State or gstHHThinking; |
265 Me.Message:= 0; |
206 Me.Message:= 0; |
266 StopThinking:= false; |
|
267 ThinkingHH:= Me; |
|
268 FillTargets; |
207 FillTargets; |
269 if Targets.Count = 0 then |
208 if Targets.Count = 0 then |
270 begin |
209 begin |
271 OutError('AI: no targets!?'); |
210 OutError('AI: no targets!?'); |
272 exit |
211 exit |
273 end; |
212 end; |
|
213 |
274 FillBonuses((Me.State and gstAttacked) <> 0); |
214 FillBonuses((Me.State and gstAttacked) <> 0); |
|
215 |
275 for a:= Low(TAmmoType) to High(TAmmoType) do |
216 for a:= Low(TAmmoType) to High(TAmmoType) do |
276 CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me.Hedgehog), a); |
217 CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me.Hedgehog), a); |
277 {$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF} |
218 |
278 ThinkThread:= SDL_CreateThread(@Think, Me) |
219 BestActions.Count:= 0; |
279 end; |
220 BestActions.Pos:= 0; |
280 |
221 BestActions.Score:= 0; |
281 procedure ProcessBot; |
222 tmp:= random(2) + 1; |
282 const StartTicks: Longword = 0; |
223 Push(0, BestActions, Me^, tmp); |
283 begin |
224 Push(0, BestActions, Me^, tmp xor 3); |
|
225 BestActions.Score:= Low(integer); |
|
226 |
|
227 Think(Me) |
|
228 end; |
|
229 |
|
230 procedure ProcessBot(FrameNo: Longword); |
|
231 const LastFrameNo: Longword = 0; |
|
232 begin |
|
233 if FrameNo = LastFrameNo then exit; |
|
234 LastFrameNo:= FrameNo; |
284 with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do |
235 with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do |
285 if (Gear <> nil) |
236 if (Gear <> nil) |
286 and ((Gear.State and gstHHDriven) <> 0) |
237 and ((Gear.State and gstHHDriven) <> 0) |
287 and (TurnTimeLeft < cHedgehogTurnTime - 50) then |
238 and (TurnTimeLeft < cHedgehogTurnTime - 50) then |
288 if ((Gear.State and gstHHThinking) = 0) then |
239 if not isThinking then |
289 if (BestActions.Pos >= BestActions.Count) then |
240 if (BestActions.Pos >= BestActions.Count) then StartThink(Gear) |
290 begin |
241 else ProcessAction(BestActions, Gear) |
291 StartThink(Gear); |
242 else Think(Gear) |
292 StartTicks:= GameTicks |
|
293 end else ProcessAction(BestActions, Gear) |
|
294 else if (GameTicks - StartTicks) > cMaxAIThinkTime then StopThinking:= true |
|
295 end; |
243 end; |
296 |
244 |
297 end. |
245 end. |