22 {$INCLUDE options.inc} |
22 {$INCLUDE options.inc} |
23 procedure ProcessBot(FrameNo: Longword); |
23 procedure ProcessBot(FrameNo: Longword); |
24 procedure FreeActionsList; |
24 procedure FreeActionsList; |
25 |
25 |
26 implementation |
26 implementation |
27 {uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc, |
27 uses uTeams, uConsts, SDLh, uAIMisc, uGears, uAIAmmoTests, uAIActions, uMisc, |
28 uAIThinkStack, uAmmos; |
28 uAIThinkStack, uAmmos; |
29 |
29 |
30 var BestActions: TActions; |
30 var BestActions: TActions; |
31 CanUseAmmo: array [TAmmoType] of boolean; |
31 CanUseAmmo: array [TAmmoType] of boolean; |
32 AIThinkStart: Longword; |
32 AIThinkStart: Longword; |
33 isThinking: boolean = false; |
33 isThinking: boolean = false; |
34 |
34 |
35 }procedure FreeActionsList; |
35 procedure FreeActionsList; |
36 begin |
36 begin |
37 {isThinking:= false; |
37 isThinking:= false; |
38 BestActions.Count:= 0; |
38 BestActions.Count:= 0; |
39 BestActions.Pos:= 0 |
39 BestActions.Pos:= 0 |
40 }end; |
40 end; |
41 { |
41 |
42 procedure TestAmmos(var Actions: TActions; Me: PGear); |
42 procedure TestAmmos(var Actions: TActions; Me: PGear); |
43 var Time, BotLevel: Longword; |
43 var Time, BotLevel: Longword; |
44 Angle, Power, Score, ExplX, ExplY, ExplR: integer; |
44 Angle, Power, Score, ExplX, ExplY, ExplR: integer; |
45 i: integer; |
45 i: integer; |
46 a, aa: TAmmoType; |
46 a, aa: TAmmoType; |
47 begin |
47 begin |
48 BotLevel:= PHedgehog(Me.Hedgehog).BotLevel; |
48 BotLevel:= PHedgehog(Me^.Hedgehog)^.BotLevel; |
49 |
49 |
50 for i:= 0 to Pred(Targets.Count) do |
50 for i:= 0 to Pred(Targets.Count) do |
51 if (Targets.ar[i].Score >= 0) then |
51 if (Targets.ar[i].Score >= 0) then |
52 begin |
52 begin |
53 with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do |
53 with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do |
54 a:= Ammo[CurSlot, CurAmmo].AmmoType; |
54 a:= Ammo^[CurSlot, CurAmmo].AmmoType; |
55 aa:= a; |
55 aa:= a; |
56 repeat |
56 repeat |
57 if CanUseAmmo[a] then |
57 if CanUseAmmo[a] then |
58 begin |
58 begin |
59 Score:= AmmoTests[a](Me, Targets.ar[i].Point, BotLevel, Time, Angle, Power, ExplX, ExplY, ExplR); |
59 Score:= AmmoTests[a](Me, Targets.ar[i].Point, BotLevel, Time, Angle, Power, ExplX, ExplY, ExplR); |
60 if Actions.Score + Score > BestActions.Score then |
60 if Actions.Score + Score > BestActions.Score then |
61 begin |
61 begin |
62 BestActions:= Actions; |
62 BestActions:= Actions; |
63 inc(BestActions.Score, Score); |
63 inc(BestActions.Score, Score); |
64 |
64 |
65 AddAction(BestActions, aia_Weapon, Longword(a), 500); |
65 AddAction(BestActions, aia_Weapon, Longword(a), 500, 0, 0); |
66 if Time <> 0 then AddAction(BestActions, aia_Timer, Time div 1000, 400); |
66 if Time <> 0 then AddAction(BestActions, aia_Timer, Time div 1000, 400, 0, 0); |
67 if (Angle > 0) then AddAction(BestActions, aia_LookRight, 0, 200) |
67 if (Angle > 0) then AddAction(BestActions, aia_LookRight, 0, 200, 0, 0) |
68 else if (Angle < 0) then AddAction(BestActions, aia_LookLeft, 0, 200); |
68 else if (Angle < 0) then AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0); |
69 if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then |
69 if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then |
70 begin |
70 begin |
71 Angle:= integer(Me.Angle) - Abs(Angle); |
71 Angle:= integer(Me^.Angle) - Abs(Angle); |
72 if Angle > 0 then |
72 if Angle > 0 then |
73 begin |
73 begin |
74 AddAction(BestActions, aia_Up, aim_push, 500); |
74 AddAction(BestActions, aia_Up, aim_push, 500, 0, 0); |
75 AddAction(BestActions, aia_Up, aim_release, Angle) |
75 AddAction(BestActions, aia_Up, aim_release, Angle, 0, 0) |
76 end else if Angle < 0 then |
76 end else if Angle < 0 then |
77 begin |
77 begin |
78 AddAction(BestActions, aia_Down, aim_push, 500); |
78 AddAction(BestActions, aia_Down, aim_push, 500, 0, 0); |
79 AddAction(BestActions, aia_Down, aim_release, -Angle) |
79 AddAction(BestActions, aia_Down, aim_release, -Angle, 0, 0) |
80 end |
80 end |
81 end; |
81 end; |
82 AddAction(BestActions, aia_attack, aim_push, 800); |
82 AddAction(BestActions, aia_attack, aim_push, 800, 0, 0); |
83 AddAction(BestActions, aia_attack, aim_release, Power); |
83 AddAction(BestActions, aia_attack, aim_release, Power, 0, 0); |
84 if ExplR > 0 then |
84 if ExplR > 0 then |
85 AddAction(BestActions, aia_AwareExpl, ExplR, 10, ExplX, ExplY); |
85 AddAction(BestActions, aia_AwareExpl, ExplR, 10, ExplX, ExplY); |
86 end |
86 end |
87 end; |
87 end; |
88 if a = High(TAmmoType) then a:= Low(TAmmoType) |
88 if a = High(TAmmoType) then a:= Low(TAmmoType) |
89 else inc(a) |
89 else inc(a) |
90 until (a = aa) or (PHedgehog(Me.Hedgehog).AttacksNum > 0) |
90 until (a = aa) or (PHedgehog(Me^.Hedgehog)^.AttacksNum > 0) |
91 end |
91 end |
92 end; |
92 end; |
93 |
93 |
94 procedure Walk(Me: PGear); |
94 procedure Walk(Me: PGear); |
95 const FallPixForBranching = cHHRadius * 2 + 8; |
95 const FallPixForBranching = cHHRadius * 2 + 8; |
113 begin |
113 begin |
114 isThinking:= false; |
114 isThinking:= false; |
115 exit |
115 exit |
116 end; |
116 end; |
117 |
117 |
118 AddAction(Actions, Me.Message, aim_push, 10); |
118 AddAction(Actions, Me^.Message, aim_push, 10, 0, 0); |
119 if (Me.Message and gm_Left) <> 0 then AddAction(Actions, aia_WaitXL, round(Me.X), 0) |
119 if (Me^.Message and gm_Left) <> 0 then AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0) |
120 else AddAction(Actions, aia_WaitXR, round(Me.X), 0); |
120 else AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0); |
121 AddAction(Actions, Me.Message, aim_release, 0); |
121 AddAction(Actions, Me^.Message, aim_release, 0, 0, 0); |
122 steps:= 0; |
122 steps:= 0; |
123 if ((Me.State and gstAttacked) = 0) then TestAmmos(Actions, Me); |
123 if ((Me^.State and gstAttacked) = 0) then TestAmmos(Actions, Me); |
124 |
124 |
125 while not PosInThinkStack(Me) do |
125 while not PosInThinkStack(Me) do |
126 begin |
126 begin |
127 CanGo:= HHGo(Me, @AltMe, GoInfo); |
127 CanGo:= HHGo(Me, @AltMe, GoInfo); |
128 inc(ticks, GoInfo.Ticks); |
128 inc(ticks, GoInfo.Ticks); |
130 |
130 |
131 if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support |
131 if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support |
132 if Push(ticks, Actions, AltMe, Me^.Message) then |
132 if Push(ticks, Actions, AltMe, Me^.Message) then |
133 with ThinkStack.States[Pred(ThinkStack.Count)] do |
133 with ThinkStack.States[Pred(ThinkStack.Count)] do |
134 begin |
134 begin |
135 AddAction(MadeActions, aia_HJump, 0, 305); |
135 AddAction(MadeActions, aia_HJump, 0, 305, 0, 0); |
136 AddAction(MadeActions, aia_HJump, 0, 350); |
136 AddAction(MadeActions, aia_HJump, 0, 350, 0, 0); |
137 if (Me.dX < 0) then AddAction(MadeActions, aia_WaitXL, round(AltMe.X), 0) |
137 if (Me^.dX < 0) then AddAction(MadeActions, aia_WaitXL, hwRound(AltMe.X), 0, 0, 0) |
138 else AddAction(MadeActions, aia_WaitXR, round(AltMe.X), 0); |
138 else AddAction(MadeActions, aia_WaitXR, hwRound(AltMe.X), 0, 0, 0); |
139 end; |
139 end; |
140 if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support |
140 if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support |
141 if Push(ticks, Actions, AltMe, Me^.Message) then |
141 if Push(ticks, Actions, AltMe, Me^.Message) then |
142 with ThinkStack.States[Pred(ThinkStack.Count)] do |
142 with ThinkStack.States[Pred(ThinkStack.Count)] do |
143 begin |
143 begin |
144 AddAction(MadeActions, aia_LJump, 0, 305); |
144 AddAction(MadeActions, aia_LJump, 0, 305, 0, 0); |
145 if (Me.dX < 0) then AddAction(MadeActions, aia_WaitXL, round(AltMe.X), 0) |
145 if (Me^.dX < 0) then AddAction(MadeActions, aia_WaitXL, hwRound(AltMe.X), 0, 0, 0) |
146 else AddAction(MadeActions, aia_WaitXR, round(AltMe.X), 0); |
146 else AddAction(MadeActions, aia_WaitXR, hwRound(AltMe.X), 0, 0, 0); |
147 end; |
147 end; |
148 |
148 |
149 if not CanGo then break; |
149 if not CanGo then break; |
150 inc(steps); |
150 inc(steps); |
151 Actions.actions[Actions.Count - 2].Param:= round(Me.X); |
151 Actions.actions[Actions.Count - 2].Param:= hwRound(Me^.X); |
152 Rate:= RatePlace(Me); |
152 Rate:= RatePlace(Me); |
153 if Rate > BaseRate then |
153 if Rate > BaseRate then |
154 begin |
154 begin |
155 BestActions:= Actions; |
155 BestActions:= Actions; |
156 BestActions.Score:= 1; |
156 BestActions.Score:= 1; |
180 var BackMe, WalkMe: TGear; |
180 var BackMe, WalkMe: TGear; |
181 begin |
181 begin |
182 AIThinkStart:= SDL_GetTicks; |
182 AIThinkStart:= SDL_GetTicks; |
183 BackMe:= Me^; |
183 BackMe:= Me^; |
184 WalkMe:= BackMe; |
184 WalkMe:= BackMe; |
185 if (Me.State and gstAttacked) = 0 then |
185 if (Me^.State and gstAttacked) = 0 then |
186 if Targets.Count > 0 then |
186 if Targets.Count > 0 then |
187 begin |
187 begin |
188 Walk(@WalkMe); |
188 Walk(@WalkMe); |
189 if not isThinking then |
189 if not isThinking then |
190 begin |
190 begin |
191 if BestActions.Score < -1023 then |
191 if BestActions.Score < -1023 then |
192 begin |
192 begin |
193 BestActions.Count:= 0; |
193 BestActions.Count:= 0; |
194 AddAction(BestActions, aia_Skip, 0, 250); |
194 AddAction(BestActions, aia_Skip, 0, 250, 0, 0); |
195 end; |
195 end; |
196 Me.State:= Me.State and not gstHHThinking |
196 Me^.State:= Me^.State and not gstHHThinking |
197 end |
197 end |
198 end else |
198 end else |
199 else begin |
199 else begin |
200 FillBonuses(true); |
200 FillBonuses(true); |
201 Walk(@WalkMe); |
201 Walk(@WalkMe); |
202 AddAction(BestActions, aia_Wait, GameTicks + 100, 100); |
202 AddAction(BestActions, aia_Wait, GameTicks + 100, 100, 0, 0); |
203 end |
203 end |
204 end; |
204 end; |
205 |
205 |
206 procedure StartThink(Me: PGear); |
206 procedure StartThink(Me: PGear); |
207 var a: TAmmoType; |
207 var a: TAmmoType; |
208 tmp: integer; |
208 tmp: integer; |
209 begin |
209 begin |
210 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit; |
210 if ((Me^.State and gstAttacking) <> 0) or isInMultiShoot then exit; |
211 ThinkingHH:= Me; |
211 ThinkingHH:= Me; |
212 isThinking:= true; |
212 isThinking:= true; |
213 |
213 |
214 ClearThinkStack; |
214 ClearThinkStack; |
215 |
215 |
216 Me.State:= Me.State or gstHHThinking; |
216 Me^.State:= Me^.State or gstHHThinking; |
217 Me.Message:= 0; |
217 Me^.Message:= 0; |
218 FillTargets; |
218 FillTargets; |
219 if Targets.Count = 0 then |
219 if Targets.Count = 0 then |
220 begin |
220 begin |
221 OutError('AI: no targets!?'); |
221 OutError('AI: no targets!?', false); |
222 exit |
222 exit |
223 end; |
223 end; |
224 |
224 |
225 FillBonuses((Me.State and gstAttacked) <> 0); |
225 FillBonuses((Me^.State and gstAttacked) <> 0); |
226 |
226 |
227 for a:= Low(TAmmoType) to High(TAmmoType) do |
227 for a:= Low(TAmmoType) to High(TAmmoType) do |
228 CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me.Hedgehog), a); |
228 CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me^.Hedgehog), a); |
229 |
229 |
230 BestActions.Count:= 0; |
230 BestActions.Count:= 0; |
231 BestActions.Pos:= 0; |
231 BestActions.Pos:= 0; |
232 BestActions.Score:= 0; |
232 BestActions.Score:= 0; |
233 tmp:= random(2) + 1; |
233 tmp:= random(2) + 1; |
234 Push(0, BestActions, Me^, tmp); |
234 Push(0, BestActions, Me^, tmp); |
235 Push(0, BestActions, Me^, tmp xor 3); |
235 Push(0, BestActions, Me^, tmp xor 3); |
236 BestActions.Score:= Low(integer); |
236 BestActions.Score:= Low(integer); |
237 |
237 |
238 Think(Me) |
238 Think(Me) |
239 end; } |
239 end; |
240 |
240 |
241 procedure ProcessBot(FrameNo: Longword); |
241 procedure ProcessBot(FrameNo: Longword); |
242 //const LastFrameNo: Longword = 0; |
242 const LastFrameNo: Longword = 0; |
243 begin |
243 begin |
244 {with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do |
244 with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do |
245 if (Gear <> nil) |
245 if (Gear <> nil) |
246 and ((Gear.State and gstHHDriven) <> 0) |
246 and ((Gear^.State and gstHHDriven) <> 0) |
247 and (TurnTimeLeft < cHedgehogTurnTime - 50) then |
247 and (TurnTimeLeft < cHedgehogTurnTime - 50) then |
248 if not isThinking then |
248 if not isThinking then |
249 if (BestActions.Pos >= BestActions.Count) then StartThink(Gear) |
249 if (BestActions.Pos >= BestActions.Count) then StartThink(Gear) |
250 else ProcessAction(BestActions, Gear) |
250 else ProcessAction(BestActions, Gear) |
251 else if FrameNo <> LastFrameNo then |
251 else if FrameNo <> LastFrameNo then |
252 begin |
252 begin |
253 LastFrameNo:= FrameNo; |
253 LastFrameNo:= FrameNo; |
254 Think(Gear) |
254 Think(Gear) |
255 end; |
255 end; |
256 }end; |
256 end; |
257 |
257 |
258 end. |
258 end. |