1 | {$INCLUDE Switches.inc}
|
---|
2 | unit Barbarina;
|
---|
3 |
|
---|
4 | interface
|
---|
5 |
|
---|
6 | uses
|
---|
7 | {$IFDEF DEBUG}SysUtils,{$ENDIF} // necessary for debug exceptions
|
---|
8 | {$IFDEF DEBUG}Names,{$ENDIF}
|
---|
9 | Protocol, ToolAI, CustomAI;
|
---|
10 |
|
---|
11 | const
|
---|
12 | nModelCategory = 4;
|
---|
13 | ctGroundSlow = 0;
|
---|
14 | ctGroundFast = 1;
|
---|
15 | ctSeaTrans = 2;
|
---|
16 | ctSeaArt = 3;
|
---|
17 |
|
---|
18 | maxCOD = 256;
|
---|
19 |
|
---|
20 | maxModern = 16;
|
---|
21 | // maximum number of modern resources of one type being managed
|
---|
22 | // (for designed maps only, number is 2 in standard game)
|
---|
23 |
|
---|
24 |
|
---|
25 | type
|
---|
26 | TColonyShipPlan = array[0..nShipPart - 1] of record
|
---|
27 | cixProducing: Integer;
|
---|
28 | LocResource: array[0..maxModern - 1] of Integer;
|
---|
29 | nLocResource: Integer;
|
---|
30 | LocFoundCity: array[0..maxModern - 1] of Integer;
|
---|
31 | nLocFoundCity: Integer;
|
---|
32 | end;
|
---|
33 |
|
---|
34 | TBarbarina = class(TToolAI)
|
---|
35 | constructor Create(Nation: Integer); override;
|
---|
36 | protected
|
---|
37 | ColonyShipPlan: TColonyShipPlan;
|
---|
38 | function Barbarina_GoHidden: Boolean; // whether we should prepare for barbarina mode
|
---|
39 | function Barbarina_Go: Boolean; // whether we should switch to barbarina mode now
|
---|
40 | procedure Barbarina_DoTurn;
|
---|
41 | procedure Barbarina_SetCityProduction;
|
---|
42 | function Barbarina_ChooseResearchAdvance: Integer;
|
---|
43 | function Barbarina_WantCheckNegotiation(Nation: Integer): Boolean;
|
---|
44 | procedure Barbarina_DoCheckNegotiation;
|
---|
45 | function Barbarina_WantNegotiation(Nation: Integer; NegoTime: TNegoTime): Boolean;
|
---|
46 | procedure Barbarina_DoNegotiation;
|
---|
47 | procedure MakeColonyShipPlan;
|
---|
48 | private
|
---|
49 | TurnOfMapAnalysis, Neighbours: Integer;
|
---|
50 | ContinentPresence: array[0..maxCOD - 1] of Integer;
|
---|
51 | OceanPresence: array[0..maxCOD - 1] of Integer;
|
---|
52 | ContinentSize: array[0..maxCOD - 1] of Integer;
|
---|
53 | OceanSize: array[0..maxCOD - 1] of Integer;
|
---|
54 | mixBest: array[0..nModelCategory - 1] of Integer;
|
---|
55 | NegoCause: (CancelTreaty);
|
---|
56 | function IsModelAvailable(rmix: Integer): Boolean;
|
---|
57 | procedure FindBestModels;
|
---|
58 | procedure AnalyzeMap;
|
---|
59 | procedure RateAttack(uix: Integer);
|
---|
60 | function DoAttack(uix, AttackLoc: Integer): Boolean;
|
---|
61 | function ProcessMove(uix: Integer): Boolean;
|
---|
62 | procedure AttackAndPatrol;
|
---|
63 | end;
|
---|
64 |
|
---|
65 |
|
---|
66 | implementation
|
---|
67 |
|
---|
68 | uses
|
---|
69 | Pile;
|
---|
70 |
|
---|
71 | type
|
---|
72 | TResearchModel = record
|
---|
73 | Category, Domain, Weight, adStop, FutMStrength: Integer;
|
---|
74 | Upgrades: Cardinal;
|
---|
75 | Cap: array [0..nFeature - 1] of Integer;
|
---|
76 | end;
|
---|
77 |
|
---|
78 | const
|
---|
79 | //UnitKind
|
---|
80 | ukSlow = $01;
|
---|
81 | ukFast = $02;
|
---|
82 |
|
---|
83 | neumax = 4096;
|
---|
84 | mixTownGuard = 2;
|
---|
85 |
|
---|
86 | PresenceUnknown = $10000;
|
---|
87 |
|
---|
88 | WonderProductionThreshold = 15;
|
---|
89 | WonderInclination = 24.0; // higher value means lower probability of building wonder
|
---|
90 | ReduceDefense = 16; // if this is x, 1/x of all units is used to defend cities
|
---|
91 |
|
---|
92 | nResearchOrder = 40;
|
---|
93 | ResearchOrder: array[0..nResearchOrder - 1] of Integer =
|
---|
94 | (adBronzeWorking, -adMapMaking, adChivalry, adMonotheism, adIronWorking,
|
---|
95 | adGunPowder, adTheology, adConstruction, adCodeOfLaws, -adEngineering,
|
---|
96 | -adSeafaring, -adNavigation, adMetallurgy, adBallistics, adScience, adExplosives,
|
---|
97 | adTactics, adSteel, -adSteamEngine, -adAmphibiousWarfare, -adMagnetism, adRadio,
|
---|
98 | adAutomobile, adMobileWarfare, adRailroad, adCommunism, adDemocracy,
|
---|
99 | adTheCorporation, adMassProduction, adIndustrialization, adRobotics, adComposites,
|
---|
100 | adTheLaser, adFlight, adAdvancedFlight, adSpaceFlight,
|
---|
101 | adSyntheticFood, adTransstellarColonization, adElectronics, adSmartWeapons);
|
---|
102 |
|
---|
103 | nResearchModel = 16;
|
---|
104 | ResearchModel: array[0..nResearchModel - 1] of TResearchModel =
|
---|
105 | // Wea Arm Mob Sea Car Tur Bom Fue Air Nav Rad Sub Art Alp Sup Ove Air Spy SE NP Jet Ste Fan Fir Wil Aca Lin
|
---|
106 | ((Category: ctGroundSlow; Domain: dGround; Weight: 7; adStop: adIronWorking;
|
---|
107 | Upgrades: $0003;
|
---|
108 | Cap: (3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
109 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
110 | (Category: ctGroundFast; Domain: dGround; Weight: 7; adStop: adIronWorking;
|
---|
111 | Upgrades: $0003;
|
---|
112 | Cap: (3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
113 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
114 | (Category: ctGroundSlow; Domain: dGround; Weight: 7; adStop: adExplosives;
|
---|
115 | Upgrades: $003F;
|
---|
116 | Cap: (3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
117 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
118 | (Category: ctGroundFast; Domain: dGround; Weight: 7; adStop: adExplosives;
|
---|
119 | Upgrades: $003F;
|
---|
120 | Cap: (3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
121 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
122 | (Category: ctSeaTrans; Domain: dSea; Weight: 7; adStop: adExplosives;
|
---|
123 | Upgrades: $000F;
|
---|
124 | Cap: (0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
125 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
126 | (Category: ctSeaArt; Domain: dSea; Weight: 7; adStop: adExplosives; Upgrades: $000F;
|
---|
127 | Cap: (4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
---|
128 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
129 | (Category: ctGroundSlow; Domain: dGround; Weight: 7; adStop: adAutomobile;
|
---|
130 | Upgrades: $00FF;
|
---|
131 | Cap: (1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
132 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
133 | (Category: ctGroundFast; Domain: dGround; Weight: 7; adStop: adAutomobile;
|
---|
134 | Upgrades: $00FF;
|
---|
135 | Cap: (3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
---|
136 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
137 | (Category: ctSeaTrans; Domain: dSea; Weight: 9; adStop: -1; Upgrades: $00FF;
|
---|
138 | Cap: (0, 4, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
---|
139 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
140 | (Category: ctSeaArt; Domain: dSea; Weight: 9; adStop: -1; Upgrades: $00FF;
|
---|
141 | Cap: (5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
|
---|
142 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
143 | (Category: ctGroundSlow; Domain: dGround; Weight: 10; adStop: adCommunism;
|
---|
144 | Upgrades: $05FF;
|
---|
145 | Cap: (3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
---|
146 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
147 | (Category: ctGroundFast; Domain: dGround; Weight: 10; adStop: adCommunism;
|
---|
148 | Upgrades: $05FF;
|
---|
149 | Cap: (5, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
---|
150 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
|
---|
151 | (Category: ctGroundSlow; Domain: dGround; Weight: 10; adStop: adComposites;
|
---|
152 | Upgrades: $07FF;
|
---|
153 | Cap: (3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
---|
154 | 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1)),
|
---|
155 | (Category: ctGroundFast; Domain: dGround; Weight: 10; adStop: adComposites;
|
---|
156 | Upgrades: $07FF;
|
---|
157 | Cap: (5, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
---|
158 | 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1)),
|
---|
159 | (Category: ctGroundSlow; Domain: dGround; Weight: 10; adStop: -1; Upgrades: $3FFF;
|
---|
160 | Cap: (3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
---|
161 | 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1)),
|
---|
162 | (Category: ctGroundFast; Domain: dGround; Weight: 10; adStop: -1; Upgrades: $3FFF;
|
---|
163 | Cap: (5, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
---|
164 | 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1)));
|
---|
165 | EntryModel_Base = 1;
|
---|
166 | EntryModel_GunPowder = 3;
|
---|
167 | EntryModel_MassProduction = 13;
|
---|
168 |
|
---|
169 |
|
---|
170 | var
|
---|
171 | Moved: array[0..numax - 1] of Boolean;
|
---|
172 | UnitPresence: array[0..lxmax * lymax - 1] of Byte;
|
---|
173 | euixMap: array[0..lxmax * lymax - 1] of SmallInt;
|
---|
174 | uixAttack: array[0..neumax - 1] of SmallInt;
|
---|
175 | AttackScore: array[0..neumax - 1] of Integer;
|
---|
176 |
|
---|
177 | constructor TBarbarina.Create(Nation: Integer);
|
---|
178 | begin
|
---|
179 | inherited;
|
---|
180 | TurnOfMapAnalysis := -1;
|
---|
181 | end;
|
---|
182 |
|
---|
183 | // whether one of the existing models matches a specific research model
|
---|
184 | function TBarbarina.IsModelAvailable(rmix: Integer): Boolean;
|
---|
185 | var
|
---|
186 | I, mix, MStrength: Integer;
|
---|
187 | begin
|
---|
188 | Result := False;
|
---|
189 | with ResearchModel[rmix] do
|
---|
190 | begin
|
---|
191 | MStrength := CurrentMStrength(Domain);
|
---|
192 | for mix := 3 to RO.nModel - 1 do
|
---|
193 | if ((MyModel[mix].kind = mkSelfDeveloped) or
|
---|
194 | (MyModel[mix].kind = mkEnemyDeveloped)) and (MyModel[mix].Domain = Domain) and
|
---|
195 | (Upgrades and not MyModel[mix].Upgrades = 0) then
|
---|
196 | begin
|
---|
197 | Result := MStrength < (MyModel[mix].MStrength * 3) div 2;
|
---|
198 | // for future techs: don't count model available if 50% stronger possible
|
---|
199 | for I := 0 to nFeature - 1 do
|
---|
200 | if MyModel[mix].Cap[I] < Cap[I] then
|
---|
201 | begin
|
---|
202 | Result := False;
|
---|
203 | Break;
|
---|
204 | end;
|
---|
205 | if Result then
|
---|
206 | Break;
|
---|
207 | end;
|
---|
208 | end;
|
---|
209 | end;
|
---|
210 |
|
---|
211 | function TBarbarina.Barbarina_GoHidden: Boolean;
|
---|
212 | var
|
---|
213 | V21, Loc1, cix: Integer;
|
---|
214 | Radius: TVicinity21Loc;
|
---|
215 | begin
|
---|
216 | if IsResearched(adMassProduction) then
|
---|
217 | begin
|
---|
218 | Result := True;
|
---|
219 | for cix := 0 to RO.nCity - 1 do
|
---|
220 | with MyCity[cix] do
|
---|
221 | if Loc >= 0 then
|
---|
222 | begin // search for modern resource
|
---|
223 | V21_to_Loc(Loc, Radius);
|
---|
224 | for V21 := 1 to 26 do
|
---|
225 | begin
|
---|
226 | Loc1 := Radius[V21];
|
---|
227 | if (Loc1 >= 0) and (RO.Map[Loc1] and fModern <> 0) then
|
---|
228 | Result := False;
|
---|
229 | end;
|
---|
230 | end;
|
---|
231 | end
|
---|
232 | else if IsResearched(adGunPowder) then
|
---|
233 | Result := (RO.Tech[adTheRepublic] < tsSeen) and IsResearched(adTheology)
|
---|
234 | else
|
---|
235 | Result := False;
|
---|
236 | end;
|
---|
237 |
|
---|
238 | function TBarbarina.Barbarina_Go: Boolean;
|
---|
239 | begin
|
---|
240 | if IsResearched(adMassProduction) then
|
---|
241 | Result := IsResearched(adTheology) and IsModelAvailable(EntryModel_MassProduction)
|
---|
242 | else if IsResearched(adGunPowder) then
|
---|
243 | Result := IsResearched(adTheology) and IsResearched(adMapMaking) and
|
---|
244 | IsModelAvailable(EntryModel_GunPowder)
|
---|
245 | else
|
---|
246 | begin
|
---|
247 | Result := (RO.nCity >= 3) and IsResearched(adMapMaking) and
|
---|
248 | IsModelAvailable(EntryModel_Base);
|
---|
249 | Exit;
|
---|
250 | end;
|
---|
251 | Result := Result and ((RO.nUn >= RO.nCity * 3) or
|
---|
252 | (RO.Wonder[woZeus].EffectiveOwner = Me));
|
---|
253 | end;
|
---|
254 |
|
---|
255 | procedure TBarbarina.AnalyzeMap;
|
---|
256 | var
|
---|
257 | Loc, Loc1, V8, f1, p1, cix: Integer;
|
---|
258 | Adjacent: TVicinity8Loc;
|
---|
259 | begin
|
---|
260 | if TurnOfMapAnalysis = RO.Turn then
|
---|
261 | Exit;
|
---|
262 |
|
---|
263 | // inherited;
|
---|
264 |
|
---|
265 | // collect nation presence information for continents and oceans
|
---|
266 | FillChar(ContinentPresence, SizeOf(ContinentPresence), 0);
|
---|
267 | FillChar(OceanPresence, SizeOf(OceanPresence), 0);
|
---|
268 | FillChar(ContinentSize, SizeOf(ContinentSize), 0);
|
---|
269 | FillChar(OceanSize, SizeOf(OceanSize), 0);
|
---|
270 | for Loc := 0 to MapSize - 1 do
|
---|
271 | begin
|
---|
272 | f1 := Formation[Loc];
|
---|
273 | case f1 of
|
---|
274 | 0..maxCOD - 1:
|
---|
275 | begin
|
---|
276 | p1 := RO.Territory[Loc];
|
---|
277 | if p1 >= 0 then
|
---|
278 | if Map[Loc] and fTerrain >= fGrass then
|
---|
279 | begin
|
---|
280 | Inc(ContinentSize[f1]);
|
---|
281 | ContinentPresence[f1] := ContinentPresence[f1] or (1 shl p1);
|
---|
282 | end
|
---|
283 | else
|
---|
284 | begin
|
---|
285 | Inc(OceanSize[f1]);
|
---|
286 | OceanPresence[f1] := OceanPresence[f1] or (1 shl p1);
|
---|
287 | end;
|
---|
288 | end;
|
---|
289 | nfUndiscovered:
|
---|
290 | begin // adjacent formations are not completely discovered
|
---|
291 | V8_to_Loc(Loc, Adjacent);
|
---|
292 | for V8 := 0 to 7 do
|
---|
293 | begin
|
---|
294 | Loc1 := Adjacent[V8];
|
---|
295 | if Loc1 >= 0 then
|
---|
296 | begin
|
---|
297 | f1 := Formation[Loc1];
|
---|
298 | if (f1 >= 0) and (f1 < maxCOD) then
|
---|
299 | if Map[Loc1] and fTerrain >= fGrass then
|
---|
300 | ContinentPresence[f1] := ContinentPresence[f1] or PresenceUnknown
|
---|
301 | else
|
---|
302 | OceanPresence[f1] := OceanPresence[f1] or PresenceUnknown;
|
---|
303 | end;
|
---|
304 | end;
|
---|
305 | end;
|
---|
306 | nfPeace:
|
---|
307 | begin // nation present in adjacent formations
|
---|
308 | V8_to_Loc(Loc, Adjacent);
|
---|
309 | for V8 := 0 to 7 do
|
---|
310 | begin
|
---|
311 | Loc1 := Adjacent[V8];
|
---|
312 | if Loc1 >= 0 then
|
---|
313 | begin
|
---|
314 | f1 := Formation[Loc1];
|
---|
315 | if (f1 >= 0) and (f1 < maxCOD) then
|
---|
316 | if Map[Loc1] and fTerrain >= fGrass then
|
---|
317 | ContinentPresence[f1] :=
|
---|
318 | ContinentPresence[f1] or (1 shl RO.Territory[Loc])
|
---|
319 | else
|
---|
320 | OceanPresence[f1] := OceanPresence[f1] or (1 shl RO.Territory[Loc]);
|
---|
321 | end;
|
---|
322 | end;
|
---|
323 | end;
|
---|
324 | end;
|
---|
325 | end;
|
---|
326 |
|
---|
327 | Neighbours := 0;
|
---|
328 | for cix := 0 to RO.nCity - 1 do
|
---|
329 | with MyCity[cix] do
|
---|
330 | if (Loc >= 0) and (Formation[Loc] >= 0) and (Formation[Loc] < maxCOD) then
|
---|
331 | Neighbours := Neighbours or ContinentPresence[Formation[Loc]];
|
---|
332 | Neighbours := Neighbours and not PresenceUnknown;
|
---|
333 |
|
---|
334 | TurnOfMapAnalysis := RO.Turn;
|
---|
335 | end;
|
---|
336 |
|
---|
337 | procedure TBarbarina.FindBestModels;
|
---|
338 | var
|
---|
339 | I, mix, rmix, cat: Integer;
|
---|
340 | begin
|
---|
341 | for I := 0 to nModelCategory - 1 do
|
---|
342 | mixBest[I] := -1;
|
---|
343 | for rmix := nResearchModel - 1 downto 0 do
|
---|
344 | with ResearchModel[rmix] do
|
---|
345 | if mixBest[Category] < 0 then
|
---|
346 | for mix := 3 to RO.nModel - 1 do
|
---|
347 | if (MyModel[mix].Domain = Domain) and
|
---|
348 | (Upgrades and not MyModel[mix].Upgrades = 0) then
|
---|
349 | begin
|
---|
350 | mixBest[Category] := mix;
|
---|
351 | for I := 0 to nFeature - 1 do
|
---|
352 | if MyModel[mix].Cap[I] < Cap[I] then
|
---|
353 | begin
|
---|
354 | mixBest[Category] := -1;
|
---|
355 | Break;
|
---|
356 | end;
|
---|
357 | if mixBest[Category] >= 0 then
|
---|
358 | Break;
|
---|
359 | end;
|
---|
360 | for mix := 3 to RO.nModel - 1 do
|
---|
361 | with MyModel[mix] do
|
---|
362 | if Kind <= mkEnemyDeveloped then
|
---|
363 | begin
|
---|
364 | cat := -1;
|
---|
365 | case Domain of
|
---|
366 | dGround:
|
---|
367 | if Speed >= 250 then
|
---|
368 | cat := ctGroundFast
|
---|
369 | else
|
---|
370 | cat := ctGroundSlow;
|
---|
371 | dSea:
|
---|
372 | if Cap[mcSeaTrans] > 0 then
|
---|
373 | cat := ctSeaTrans
|
---|
374 | else if Cap[mcArtillery] > 0 then
|
---|
375 | cat := ctSeaArt;
|
---|
376 | end;
|
---|
377 | if (cat >= 0) and (mix <> mixBest[cat]) and
|
---|
378 | ((mixBest[cat] < 0) or (Weight * MStrength > MyModel[mixBest[cat]].Weight +
|
---|
379 | MyModel[mixBest[cat]].MStrength)) then
|
---|
380 | mixBest[cat] := mix;
|
---|
381 | end;
|
---|
382 | if (mixBest[ctSeaTrans] < 0) and not IsResearched(adExplosives) then // longboat?
|
---|
383 | for mix := 3 to RO.nModel - 1 do
|
---|
384 | if MyModel[mix].Cap[mcSeaTrans] > 0 then
|
---|
385 | begin
|
---|
386 | mixBest[ctSeaTrans] := mix;
|
---|
387 | Break;
|
---|
388 | end;
|
---|
389 | end;
|
---|
390 |
|
---|
391 | procedure TBarbarina.Barbarina_DoTurn;
|
---|
392 | begin
|
---|
393 | if (RO.Government in [gRepublic, gDemocracy, gFuture]) or
|
---|
394 | (RO.Government <> gFundamentalism) and (RO.Government <> gAnarchy) and
|
---|
395 | IsResearched(adTheology) then
|
---|
396 | Revolution;
|
---|
397 |
|
---|
398 | AnalyzeMap;
|
---|
399 |
|
---|
400 | FindBestModels;
|
---|
401 |
|
---|
402 | AttackAndPatrol;
|
---|
403 | end;
|
---|
404 |
|
---|
405 | // find one unit to destroy each known enemy unit, result in uixAttack
|
---|
406 | procedure TBarbarina.RateAttack(uix: Integer);
|
---|
407 | var
|
---|
408 | MoveStyle, TestLoc, TestTime, NextLoc, NextTime, V8, RemHealth,
|
---|
409 | RecoverTurns, Score, BestScore, euixBest, uixOld: Integer;
|
---|
410 | NextTile: Cardinal;
|
---|
411 | Adjacent: TVicinity8Loc;
|
---|
412 | Defense: ^TUnitInfo;
|
---|
413 | Reached: array[0..lxmax * lymax - 1] of Boolean;
|
---|
414 | begin
|
---|
415 | with MyUnit[uix] do
|
---|
416 | if Movement > 0 then
|
---|
417 | begin
|
---|
418 | BestScore := 0;
|
---|
419 | FillChar(Reached, MapSize, False);
|
---|
420 | MoveStyle := GetMyMoveStyle(mix, Health);
|
---|
421 | Pile.Create(MapSize);
|
---|
422 | Pile.Put(Loc, $800 - Movement);
|
---|
423 | while Pile.Get(TestLoc, TestTime) do
|
---|
424 | begin
|
---|
425 | Reached[TestLoc] := True;
|
---|
426 | V8_to_Loc(TestLoc, Adjacent);
|
---|
427 | for V8 := 0 to 7 do
|
---|
428 | begin
|
---|
429 | NextLoc := Adjacent[V8];
|
---|
430 | if (NextLoc >= 0) and not Reached[NextLoc] then
|
---|
431 | begin
|
---|
432 | NextTile := Map[NextLoc];
|
---|
433 | if euixMap[NextLoc] >= 0 then
|
---|
434 | begin // check attack
|
---|
435 | Defense := @RO.EnemyUn[euixMap[NextLoc]];
|
---|
436 | if Unit_AttackForecast(uix, NextLoc, $800 - TestTime, RemHealth) then
|
---|
437 | begin
|
---|
438 | if RemHealth <= 0 then // send unit into death?
|
---|
439 | begin
|
---|
440 | Score := 0;
|
---|
441 | if ($800 - TestTime >= 100) and
|
---|
442 | ((MyModel[mix].Domain = dGround) and
|
---|
443 | (NextTile and fTerrain >= fGrass) or
|
---|
444 | (MyModel[mix].Domain = dSea) and (NextTile and
|
---|
445 | fTerrain < fGrass)) and
|
---|
446 | (MyModel[mix].Attack > MyModel[mix].Defense) then
|
---|
447 | begin
|
---|
448 | Score := (Defense.Health + RemHealth) *
|
---|
449 | RO.EnemyModel[Defense.emix].Cost * 2 div MyModel[mix].Cost;
|
---|
450 | if NextTile and fCity <> 0 then
|
---|
451 | Score := Score * 4;
|
---|
452 | end;
|
---|
453 | end
|
---|
454 | else
|
---|
455 | Score := RO.EnemyModel[Defense.emix].Cost * 25 -
|
---|
456 | (Health - RemHealth) * MyModel[mix].Cost shr 4;
|
---|
457 | if (Score > BestScore) and (Score > AttackScore[euixMap[NextLoc]]) then
|
---|
458 | begin
|
---|
459 | BestScore := Score;
|
---|
460 | euixBest := euixMap[NextLoc];
|
---|
461 | end;
|
---|
462 | end;
|
---|
463 | end
|
---|
464 | else if (NextTile and (fUnit or fCity) = 0) or
|
---|
465 | (NextTile and fOwned <> 0) then
|
---|
466 | case CheckStep(MoveStyle, TestTime, V8 and 1, NextTime,
|
---|
467 | RecoverTurns, Map[TestLoc], NextTile, True) of
|
---|
468 | csOk:
|
---|
469 | if NextTime < $800 then
|
---|
470 | Pile.Put(NextLoc, NextTime);
|
---|
471 | csForbiddenTile:
|
---|
472 | Reached[NextLoc] := True; // don't check moving there again
|
---|
473 | csCheckTerritory:
|
---|
474 | if (NextTime < $800) and (RO.Territory[NextLoc] =
|
---|
475 | RO.Territory[TestLoc]) then
|
---|
476 | Pile.Put(NextLoc, NextTime);
|
---|
477 | end;
|
---|
478 | end;
|
---|
479 | end;
|
---|
480 | end;
|
---|
481 | Pile.Free;
|
---|
482 |
|
---|
483 | if BestScore > 0 then
|
---|
484 | begin
|
---|
485 | uixOld := uixAttack[euixBest];
|
---|
486 | AttackScore[euixBest] := BestScore;
|
---|
487 | uixAttack[euixBest] := uix;
|
---|
488 | if uixOld >= 0 then
|
---|
489 | RateAttack(uixOld);
|
---|
490 | end;
|
---|
491 | end;
|
---|
492 | end;
|
---|
493 |
|
---|
494 | function TBarbarina.DoAttack(uix, AttackLoc: Integer): Boolean;
|
---|
495 | // AttackLoc=maNextCity means bombard only
|
---|
496 | var
|
---|
497 | MoveResult, Kind, Temp, MoveStyle, TestLoc, TestTime, NextLoc,
|
---|
498 | NextTime, V8, RecoverTurns, ecix: Integer;
|
---|
499 | NextTile: Cardinal;
|
---|
500 | AttackPositionReached, IsBombardment: Boolean;
|
---|
501 | Adjacent: TVicinity8Loc;
|
---|
502 | PreLoc: array[0..lxmax * lymax - 1] of Word;
|
---|
503 | Reached: array[0..lxmax * lymax - 1] of Boolean;
|
---|
504 | begin
|
---|
505 | Result := False;
|
---|
506 | IsBombardment := AttackLoc = maNextCity;
|
---|
507 | with MyUnit[uix] do
|
---|
508 | begin
|
---|
509 | if (MyModel[mix].Domain = dGround) and (MyModel[mix].Attack > 0) then
|
---|
510 | if MyModel[mix].Speed >= 250 then
|
---|
511 | Kind := ukFast
|
---|
512 | else
|
---|
513 | Kind := ukSlow
|
---|
514 | else
|
---|
515 | Kind := 0;
|
---|
516 | FillChar(Reached, MapSize, False);
|
---|
517 | AttackPositionReached := False;
|
---|
518 | MoveStyle := GetMyMoveStyle(mix, Health);
|
---|
519 | Pile.Create(MapSize);
|
---|
520 | Pile.Put(Loc, $800 - Movement);
|
---|
521 | while Pile.Get(TestLoc, TestTime) do
|
---|
522 | begin
|
---|
523 | if (TestTime >= $800) or (AttackLoc = maNextCity) and (TestTime > $800 - 100) then
|
---|
524 | Break;
|
---|
525 | Reached[TestLoc] := True;
|
---|
526 | V8_to_Loc(TestLoc, Adjacent);
|
---|
527 | for V8 := 0 to 7 do
|
---|
528 | begin
|
---|
529 | NextLoc := Adjacent[V8];
|
---|
530 | if NextLoc >= 0 then
|
---|
531 | begin
|
---|
532 | if IsBombardment and (Map[NextLoc] and (fCity or
|
---|
533 | fUnit or fOwned or fObserved) = fCity or fObserved) and
|
---|
534 | (RO.Treaty[RO.Territory[NextLoc]] < trPeace) then
|
---|
535 | begin
|
---|
536 | City_FindEnemyCity(NextLoc, ecix);
|
---|
537 | Assert(ecix >= 0);
|
---|
538 | with RO.EnemyCity[ecix] do
|
---|
539 | if (Size > 2) and (Flags and ciCoastalFort = 0) then
|
---|
540 | AttackLoc := NextLoc;
|
---|
541 | end;
|
---|
542 | if (NextLoc = AttackLoc) and ((MyModel[mix].Domain <> dSea) or
|
---|
543 | (Map[TestLoc] and fTerrain < fGrass)) then
|
---|
544 | // ships can only attack from water
|
---|
545 | begin
|
---|
546 | AttackPositionReached := True;
|
---|
547 | Break;
|
---|
548 | end
|
---|
549 | else if not Reached[NextLoc] then
|
---|
550 | begin
|
---|
551 | NextTile := Map[NextLoc];
|
---|
552 | if (NextTile and (fUnit or fCity) = 0) or
|
---|
553 | (NextTile and fOwned <> 0) then
|
---|
554 | case CheckStep(MoveStyle, TestTime, V8 and 1, NextTime,
|
---|
555 | RecoverTurns, Map[TestLoc], NextTile, True) of
|
---|
556 | csOk:
|
---|
557 | if Pile.Put(NextLoc, NextTime) then
|
---|
558 | PreLoc[NextLoc] := TestLoc;
|
---|
559 | csForbiddenTile:
|
---|
560 | Reached[NextLoc] := True; // don't check moving there again
|
---|
561 | csCheckTerritory:
|
---|
562 | if RO.Territory[NextLoc] = RO.Territory[TestLoc] then
|
---|
563 | if Pile.Put(NextLoc, NextTime) then
|
---|
564 | PreLoc[NextLoc] := TestLoc;
|
---|
565 | end;
|
---|
566 | end;
|
---|
567 | end;
|
---|
568 | end;
|
---|
569 | if AttackPositionReached then
|
---|
570 | begin
|
---|
571 | PreLoc[NextLoc] := TestLoc;
|
---|
572 | Break;
|
---|
573 | end;
|
---|
574 | end;
|
---|
575 | Pile.Free;
|
---|
576 | if not AttackPositionReached then
|
---|
577 | Exit;
|
---|
578 |
|
---|
579 | TestLoc := AttackLoc;
|
---|
580 | NextLoc := PreLoc[TestLoc];
|
---|
581 | while TestLoc <> Loc do
|
---|
582 | begin
|
---|
583 | Temp := TestLoc;
|
---|
584 | TestLoc := NextLoc;
|
---|
585 | NextLoc := PreLoc[TestLoc];
|
---|
586 | PreLoc[TestLoc] := Temp;
|
---|
587 | end;
|
---|
588 |
|
---|
589 | UnitPresence[Loc] := UnitPresence[Loc] and not Kind;
|
---|
590 | // assume unit was only one of kind here
|
---|
591 | repeat
|
---|
592 | NextLoc := PreLoc[Loc];
|
---|
593 | MoveResult := Unit_Step(uix, NextLoc);
|
---|
594 | until (NextLoc = AttackLoc) or (MoveResult and rExecuted = 0) or
|
---|
595 | (MoveResult and rUnitRemoved <> 0);
|
---|
596 | Result := (NextLoc = AttackLoc) and (MoveResult and rExecuted <> 0);
|
---|
597 |
|
---|
598 | if IsBombardment and Result then
|
---|
599 | begin
|
---|
600 | City_FindEnemyCity(AttackLoc, ecix);
|
---|
601 | Assert(ecix >= 0);
|
---|
602 | while (Movement >= 100) and (RO.EnemyCity[ecix].Size > 2) do
|
---|
603 | Unit_Step(uix, AttackLoc);
|
---|
604 | end;
|
---|
605 |
|
---|
606 | if Loc >= 0 then
|
---|
607 | UnitPresence[Loc] := UnitPresence[Loc] or Kind;
|
---|
608 | end;
|
---|
609 | end;
|
---|
610 |
|
---|
611 | function TBarbarina.ProcessMove(uix: Integer): Boolean;
|
---|
612 | // return true if no new enemy spotted
|
---|
613 | const
|
---|
614 | DistanceScore = 4;
|
---|
615 | var
|
---|
616 | PatrolScore, BestCount, PatrolLoc, TestLoc, NextLoc, TestTime, V8,
|
---|
617 | TestScore, MoveResult, MoveStyle, NextTime, TerrOwner, Kind, Temp,
|
---|
618 | RecoverTurns, MaxScore: Integer;
|
---|
619 | Tile, NextTile: Cardinal;
|
---|
620 | CaptureOnly, PeaceBorder, done, NextToEnemyCity: Boolean;
|
---|
621 | Adjacent: TVicinity8Loc;
|
---|
622 | AdjacentUnknown: array[0..lxmax * lymax - 1] of ShortInt;
|
---|
623 | PreLoc: array[0..lxmax * lymax - 1] of Word;
|
---|
624 | MoreTurn: array[0..lxmax * lymax - 1] of Byte;
|
---|
625 |
|
---|
626 | begin
|
---|
627 | Result := True;
|
---|
628 | done := False;
|
---|
629 | while not done do
|
---|
630 | with MyUnit[uix] do
|
---|
631 | begin
|
---|
632 | if (MyModel[mix].Domain = dSea) and (Health < 100) and
|
---|
633 | ((Health < 34) or (MyModel[mix].Cap[mcSeaTrans] > 0)) then
|
---|
634 | begin
|
---|
635 | if Map[Loc] and fCity = 0 then
|
---|
636 | Unit_MoveEx(uix, maNextCity);
|
---|
637 | Exit;
|
---|
638 | end;
|
---|
639 |
|
---|
640 | if (MyModel[mix].Domain = dGround) and (MyModel[mix].Attack > 0) then
|
---|
641 | if MyModel[mix].Speed >= 250 then
|
---|
642 | Kind := ukFast
|
---|
643 | else
|
---|
644 | Kind := ukSlow
|
---|
645 | else
|
---|
646 | Kind := 0;
|
---|
647 | CaptureOnly := (Health < 100) and ((Map[Loc] and fCity <> 0) or
|
---|
648 | ((100 - Health) * Terrain[Map[Loc] and fTerrain].Defense > 60) and
|
---|
649 | not (Map[Loc] and fTerrain in [fOcean, fShore, fArctic, fDesert]));
|
---|
650 | MoveStyle := GetMyMoveStyle(mix, Health);
|
---|
651 |
|
---|
652 | if MyModel[mix].Attack > 0 then
|
---|
653 | MaxScore := $400
|
---|
654 | else
|
---|
655 | MaxScore := $400 - 32 + 5;
|
---|
656 | PatrolScore := -999999;
|
---|
657 | PatrolLoc := -1;
|
---|
658 | FillChar(AdjacentUnknown, MapSize, $FF); // -1, indicates tiles not checked yet
|
---|
659 | Pile.Create(MapSize);
|
---|
660 | Pile.Put(Loc, $800 - Movement);
|
---|
661 | while Pile.Get(TestLoc, TestTime) do
|
---|
662 | begin
|
---|
663 | if (MaxScore * $1000 - DistanceScore * TestTime <= PatrolScore)
|
---|
664 | // assume a score of $400 is the best achievable
|
---|
665 | or CaptureOnly and (TestTime >= $1000) then
|
---|
666 | Break;
|
---|
667 |
|
---|
668 | TestScore := 0;
|
---|
669 | Tile := Map[TestLoc];
|
---|
670 | Assert(Tile and (fUnit or fOwned) <> fUnit);
|
---|
671 | TerrOwner := RO.Territory[TestLoc];
|
---|
672 | AdjacentUnknown[TestLoc] := 0;
|
---|
673 | PeaceBorder := False;
|
---|
674 | NextToEnemyCity := False;
|
---|
675 |
|
---|
676 | if ((Tile and fCity) <> 0) and ((Tile and fOwned) = 0) then
|
---|
677 | begin
|
---|
678 | if (MyModel[mix].Domain = dGround) and (MyModel[mix].Attack > 0) and
|
---|
679 | ((TerrOwner < 0)
|
---|
680 | // happens only for unobserved cities of extinct tribes, new owner unknown
|
---|
681 | or (RO.Treaty[TerrOwner] < trPeace)) then
|
---|
682 | if (Tile and fObserved <> 0) and (Tile and fUnit = 0) then
|
---|
683 | TestScore := $400 // unfriendly undefended city -- capture!
|
---|
684 | else
|
---|
685 | TestScore := $400 - 14; // unfriendly city, not observed or defended
|
---|
686 | end
|
---|
687 |
|
---|
688 | else
|
---|
689 | begin // no enemy city or unit here
|
---|
690 | V8_to_Loc(TestLoc, Adjacent);
|
---|
691 | for V8 := 0 to 7 do
|
---|
692 | begin
|
---|
693 | NextLoc := Adjacent[V8];
|
---|
694 | if (NextLoc >= 0) and (AdjacentUnknown[NextLoc] < 0) then
|
---|
695 | begin
|
---|
696 | NextTile := Map[NextLoc];
|
---|
697 | if NextTile and fTerrain = fUNKNOWN then
|
---|
698 | Inc(AdjacentUnknown[TestLoc])
|
---|
699 | else if NextTile and fTerrain = fArctic then
|
---|
700 | else if NextTile and (fCity or fUnit or fOwned or fObserved) =
|
---|
701 | fCity or fUnit or fObserved then
|
---|
702 | NextToEnemyCity := True
|
---|
703 | else
|
---|
704 | case CheckStep(MoveStyle, TestTime, V8 and 1, NextTime,
|
---|
705 | RecoverTurns, Tile, NextTile, True) of
|
---|
706 | csOk:
|
---|
707 | { if (NextTime and $7FFFF000=TestTime and $7FFFF000)
|
---|
708 | or (UnitPresence[TestLoc] and Kind=0)
|
---|
709 | or (Tile and fCity<>0)
|
---|
710 | or (Tile and fTerImp=tiFort) or (Tile and fTerImp=tiBase) then}
|
---|
711 | begin
|
---|
712 | if Pile.Put(NextLoc, NextTime + RecoverTurns * $1000) then
|
---|
713 | begin
|
---|
714 | PreLoc[NextLoc] := TestLoc;
|
---|
715 | MoreTurn[NextLoc] := NextTime shr 12 and $FFF;
|
---|
716 | end;
|
---|
717 | end;
|
---|
718 | csForbiddenTile:
|
---|
719 | begin
|
---|
720 | AdjacentUnknown[NextLoc] := 0; // don't check moving there again
|
---|
721 | if NextTile and fPeace <> 0 then
|
---|
722 | PeaceBorder := True;
|
---|
723 | end;
|
---|
724 | csCheckTerritory:
|
---|
725 | if RO.Territory[NextLoc] = TerrOwner then
|
---|
726 | begin
|
---|
727 | if Pile.Put(NextLoc, NextTime + RecoverTurns * $1000) then
|
---|
728 | begin
|
---|
729 | PreLoc[NextLoc] := TestLoc;
|
---|
730 | MoreTurn[NextLoc] := NextTime shr 12 and $FFF;
|
---|
731 | end;
|
---|
732 | end
|
---|
733 | else
|
---|
734 | PeaceBorder := True;
|
---|
735 | end;
|
---|
736 | end;
|
---|
737 | end;
|
---|
738 | if not CaptureOnly then
|
---|
739 | if NextToEnemyCity and (MyModel[mix].Attack > 0) and
|
---|
740 | (MyModel[mix].Domain = dGround) then
|
---|
741 | TestScore := $400 - 14
|
---|
742 | else if AdjacentUnknown[TestLoc] > 0 then
|
---|
743 | if PeaceBorder or (TerrOwner >= 0) and (TerrOwner <> Me) and
|
---|
744 | (RO.Treaty[TerrOwner] < trPeace) then
|
---|
745 | TestScore := $400 - 32 + AdjacentUnknown[TestLoc]
|
---|
746 | else
|
---|
747 | TestScore := $400 - 64 + AdjacentUnknown[TestLoc]
|
---|
748 | else if PeaceBorder then
|
---|
749 | TestScore := $400 - 32
|
---|
750 | else
|
---|
751 | TestScore := (RO.Turn - RO.MapObservedLast[TestLoc]) div 16;
|
---|
752 | end; // no enemy city or unit here
|
---|
753 |
|
---|
754 | if TestScore > 0 then
|
---|
755 | begin
|
---|
756 | TestScore := TestScore * $1000 - DistanceScore * TestTime;
|
---|
757 | if TestScore > PatrolScore then
|
---|
758 | BestCount := 0;
|
---|
759 | if TestScore >= PatrolScore then
|
---|
760 | begin
|
---|
761 | Inc(BestCount);
|
---|
762 | if Random(BestCount) = 0 then
|
---|
763 | begin
|
---|
764 | PatrolScore := TestScore;
|
---|
765 | PatrolLoc := TestLoc;
|
---|
766 | end;
|
---|
767 | end;
|
---|
768 | end;
|
---|
769 | end; // while Pile.Get
|
---|
770 | Pile.Free;
|
---|
771 |
|
---|
772 | if (PatrolLoc >= 0) and (PatrolLoc <> Loc) then
|
---|
773 | begin // capture/discover/patrol task found, execute it
|
---|
774 | while (PatrolLoc <> Loc) and (MoreTurn[PatrolLoc] > 0) and
|
---|
775 | ((MoreTurn[PatrolLoc] > 1) or not (Map[PatrolLoc] and fTerrain in
|
---|
776 | [fMountains, fDesert, fArctic])) do
|
---|
777 | begin
|
---|
778 | PatrolLoc := PreLoc[PatrolLoc];
|
---|
779 | done := True; // no effect if enemy spotted
|
---|
780 | end;
|
---|
781 | while (PatrolLoc <> Loc) and (UnitPresence[PatrolLoc] and Kind <> 0) and
|
---|
782 | (Map[PatrolLoc] and fCity = 0) and (Map[PatrolLoc] and fTerImp <> tiFort) and
|
---|
783 | (Map[PatrolLoc] and fTerImp <> tiBase) and not
|
---|
784 | (Map[PreLoc[PatrolLoc]] and fTerrain in [fDesert, fArctic]) do
|
---|
785 | begin
|
---|
786 | PatrolLoc := PreLoc[PatrolLoc];
|
---|
787 | done := True; // no effect if enemy spotted
|
---|
788 | end;
|
---|
789 | if PatrolLoc = Loc then
|
---|
790 | Exit;
|
---|
791 | TestLoc := PatrolLoc;
|
---|
792 | NextLoc := PreLoc[TestLoc];
|
---|
793 | while TestLoc <> Loc do
|
---|
794 | begin
|
---|
795 | Temp := TestLoc;
|
---|
796 | TestLoc := NextLoc;
|
---|
797 | NextLoc := PreLoc[TestLoc];
|
---|
798 | PreLoc[TestLoc] := Temp;
|
---|
799 | end;
|
---|
800 |
|
---|
801 | UnitPresence[Loc] := UnitPresence[Loc] and not Kind;
|
---|
802 | // assume unit was only one of kind here
|
---|
803 | while Loc <> PatrolLoc do
|
---|
804 | begin
|
---|
805 | NextLoc := PreLoc[Loc];
|
---|
806 | MoveResult := Unit_Step(uix, NextLoc);
|
---|
807 | if (MoveResult and (rUnitRemoved or rEnemySpotted) <> 0) or
|
---|
808 | (MoveResult and rExecuted = 0) then
|
---|
809 | begin
|
---|
810 | if MoveResult and rExecuted = 0 then
|
---|
811 | Moved[uix] := True;
|
---|
812 | Result := MoveResult and rEnemySpotted = 0;
|
---|
813 | done := True;
|
---|
814 | Break;
|
---|
815 | end;
|
---|
816 | Assert(Loc = NextLoc);
|
---|
817 | end;
|
---|
818 | if Loc >= 0 then
|
---|
819 | begin
|
---|
820 | UnitPresence[Loc] := UnitPresence[Loc] or Kind;
|
---|
821 | if Map[Loc] and fCity <> 0 then
|
---|
822 | begin
|
---|
823 | Moved[uix] := True;
|
---|
824 | done := True; // stay in captured city as defender
|
---|
825 | end;
|
---|
826 | end;
|
---|
827 | end
|
---|
828 | else
|
---|
829 | done := True;
|
---|
830 | end; // while not done
|
---|
831 | if Result then
|
---|
832 | Moved[uix] := True;
|
---|
833 | end;
|
---|
834 |
|
---|
835 | procedure TBarbarina.AttackAndPatrol;
|
---|
836 |
|
---|
837 | procedure SetCityDefenders;
|
---|
838 | var
|
---|
839 | uix, cix, V8, Loc1, Best, uixBest, det: Integer;
|
---|
840 | Adjacent: TVicinity8Loc;
|
---|
841 | IsPort: Boolean;
|
---|
842 | begin
|
---|
843 | for cix := 0 to RO.nCity - 1 do
|
---|
844 | with MyCity[cix] do
|
---|
845 | if Loc >= 0 then
|
---|
846 | begin
|
---|
847 | IsPort := False;
|
---|
848 | V8_to_Loc(Loc, Adjacent);
|
---|
849 | for V8 := 0 to 7 do
|
---|
850 | begin
|
---|
851 | Loc1 := Adjacent[V8];
|
---|
852 | if (Loc1 >= 0) and (Map[Loc1] and fTerrain < fGrass) and
|
---|
853 | (Formation[Loc1] >= 0) and (Formation[Loc1] < maxCOD) and
|
---|
854 | (OceanPresence[Formation[Loc1]] and not Neighbours <> 0) then
|
---|
855 | IsPort := True;
|
---|
856 | end;
|
---|
857 | Best := -1;
|
---|
858 | for uix := 0 to RO.nUn - 1 do
|
---|
859 | if MyUnit[uix].Loc = Loc then
|
---|
860 | with MyUnit[uix] do
|
---|
861 | if (MyModel[mix].Domain = dGround) and (MyModel[mix].Attack > 0) then
|
---|
862 | begin
|
---|
863 | if (mix = 2) and (RO.Government = gDespotism) then
|
---|
864 | begin
|
---|
865 | det := 1 shl 16;
|
---|
866 | Moved[uix] := True;
|
---|
867 | end // town guard
|
---|
868 | else if IsPort then
|
---|
869 | det := MyModel[mix].Defense shl 8 + Flags and
|
---|
870 | unFortified shl 7 - health
|
---|
871 | else
|
---|
872 | det := MyModel[mix].Speed shl 8 + Flags and
|
---|
873 | unFortified shl 7 - health;
|
---|
874 | if det > Best then
|
---|
875 | begin
|
---|
876 | Best := det;
|
---|
877 | uixBest := uix;
|
---|
878 | end;
|
---|
879 | end;
|
---|
880 | if Best >= 0 then
|
---|
881 | Moved[uixBest] := True;
|
---|
882 | end;
|
---|
883 | end;
|
---|
884 |
|
---|
885 | procedure ProcessSeaTransport;
|
---|
886 | var
|
---|
887 | I, F, uix, Loc1, A, B: Integer;
|
---|
888 | Ready, Go: Boolean;
|
---|
889 | TransportPlan: TGroupTransportPlan;
|
---|
890 | begin
|
---|
891 | Go := False;
|
---|
892 | for F := 0 to maxCOD - 1 do
|
---|
893 | if (F < nContinent) and (ContinentPresence[F] and not
|
---|
894 | (1 shl Me or PresenceUnknown) <> 0) then
|
---|
895 | Go := True; // any enemy island known?
|
---|
896 | if not Go then
|
---|
897 | Exit;
|
---|
898 |
|
---|
899 | SeaTransport_BeginInitialize;
|
---|
900 | Go := False;
|
---|
901 | for uix := 0 to RO.nUn - 1 do
|
---|
902 | if not Moved[uix] then
|
---|
903 | with MyUnit[uix] do
|
---|
904 | if (Loc >= 0) and (MyModel[mix].Domain = dGround) and
|
---|
905 | (MyModel[mix].Attack > 0) and (Map[Loc] and fTerrain >= fGrass) then
|
---|
906 | begin
|
---|
907 | F := Formation[Loc];
|
---|
908 | if (F >= 0) and (F < maxCOD) and (ContinentPresence[F] and
|
---|
909 | not (1 shl Me) = 0) then
|
---|
910 | begin
|
---|
911 | go := True;
|
---|
912 | SeaTransport_AddLoad(uix);
|
---|
913 | end;
|
---|
914 | end;
|
---|
915 | if Go then
|
---|
916 | begin
|
---|
917 | Go := False;
|
---|
918 | for uix := 0 to RO.nUn - 1 do
|
---|
919 | if not Moved[uix] then
|
---|
920 | with MyUnit[uix] do
|
---|
921 | if (Loc >= 0) and (mix = mixBest[ctSeaTrans]) and
|
---|
922 | (TroopLoad = 0) and (Health = 100) then
|
---|
923 | begin
|
---|
924 | go := True;
|
---|
925 | SeaTransport_AddTransport(uix);
|
---|
926 | end;
|
---|
927 | end;
|
---|
928 | if Go then
|
---|
929 | for Loc1 := 0 to MapSize - 1 do
|
---|
930 | if Map[Loc1] and fTerrain >= fGrass then
|
---|
931 | begin
|
---|
932 | F := Formation[Loc1];
|
---|
933 | if (F >= 0) and (F < maxCOD) and (ContinentPresence[F] and
|
---|
934 | not (1 shl Me or PresenceUnknown) <> 0) then
|
---|
935 | SeaTransport_AddDestination(Loc1);
|
---|
936 | end;
|
---|
937 | SeaTransport_EndInitialize;
|
---|
938 | while SeaTransport_MakeGroupPlan(TransportPlan) do
|
---|
939 | begin
|
---|
940 | Moved[TransportPlan.uixTransport] := True;
|
---|
941 | Ready := MyUnit[TransportPlan.uixTransport].Loc = TransportPlan.LoadLoc;
|
---|
942 | if not Ready then
|
---|
943 | begin
|
---|
944 | Unit_MoveEx(TransportPlan.uixTransport, TransportPlan.LoadLoc);
|
---|
945 | Ready := MyUnit[TransportPlan.uixTransport].Loc = TransportPlan.LoadLoc;
|
---|
946 | end;
|
---|
947 | if Ready then
|
---|
948 | for I := 0 to TransportPlan.nLoad - 1 do
|
---|
949 | begin
|
---|
950 | Loc_to_ab(TransportPlan.LoadLoc,
|
---|
951 | MyUnit[TransportPlan.uixLoad[I]].Loc, A, B);
|
---|
952 | Ready := Ready and (Abs(A) <= 1) and (Abs(B) <= 1);
|
---|
953 | end;
|
---|
954 | if Ready then
|
---|
955 | begin
|
---|
956 | for I := 0 to TransportPlan.nLoad - 1 do
|
---|
957 | begin
|
---|
958 | Unit_Step(TransportPlan.uixLoad[I], TransportPlan.LoadLoc);
|
---|
959 | Moved[TransportPlan.uixLoad[I]] := True;
|
---|
960 | end;
|
---|
961 | end
|
---|
962 | else
|
---|
963 | begin
|
---|
964 | for I := 0 to TransportPlan.nLoad - 1 do
|
---|
965 | begin
|
---|
966 | Unit_MoveEx(TransportPlan.uixLoad[I], TransportPlan.LoadLoc, mxAdjacent);
|
---|
967 | Moved[TransportPlan.uixLoad[I]] := True;
|
---|
968 | end;
|
---|
969 | end;
|
---|
970 | end;
|
---|
971 | end;
|
---|
972 |
|
---|
973 | procedure ProcessUnload(uix: Integer);
|
---|
974 |
|
---|
975 | procedure Unload(Kind, ToLoc: Integer);
|
---|
976 | var
|
---|
977 | uix1: Integer;
|
---|
978 | begin
|
---|
979 | for uix1 := 0 to RO.nUn - 1 do
|
---|
980 | with MyUnit[uix1] do
|
---|
981 | if (Loc >= 0) and (Master = uix) and (MyModel[mix].Domain = dGround) and
|
---|
982 | (MyModel[mix].Attack > 0) and (Movement = MyModel[mix].Speed) and
|
---|
983 | ((MyModel[mix].Speed >= 250) = (Kind = ukFast)) then
|
---|
984 | begin
|
---|
985 | Unit_Step(uix1, ToLoc);
|
---|
986 | UnitPresence[ToLoc] := UnitPresence[ToLoc] or Kind;
|
---|
987 | Break;
|
---|
988 | end;
|
---|
989 | end;
|
---|
990 |
|
---|
991 | var
|
---|
992 | uix1, MoveStyle, TestLoc, TestTime, NextLoc, NextTime, V8,
|
---|
993 | RecoverTurns, nSlow, nFast, SlowUnloadLoc, FastUnloadLoc, EndLoc, F: Integer;
|
---|
994 | NextTile: Cardinal;
|
---|
995 | Adjacent: TVicinity8Loc;
|
---|
996 | Reached: array[0..lxmax * lymax - 1] of Boolean;
|
---|
997 | begin
|
---|
998 | // inventory
|
---|
999 | nSlow := 0;
|
---|
1000 | nFast := 0;
|
---|
1001 | for uix1 := 0 to RO.nUn - 1 do
|
---|
1002 | with MyUnit[uix1] do
|
---|
1003 | if (Loc >= 0) and (Master = uix) and (MyModel[mix].Domain = dGround) and
|
---|
1004 | (MyModel[mix].Attack > 0) then
|
---|
1005 | if MyModel[mix].Speed >= 250 then
|
---|
1006 | Inc(nFast)
|
---|
1007 | else
|
---|
1008 | Inc(nSlow);
|
---|
1009 |
|
---|
1010 | with MyUnit[uix] do
|
---|
1011 | begin
|
---|
1012 | MoveStyle := GetMyMoveStyle(mix, Health);
|
---|
1013 | repeat
|
---|
1014 | SlowUnloadLoc := -1;
|
---|
1015 | FastUnloadLoc := -1;
|
---|
1016 | EndLoc := -1;
|
---|
1017 | FillChar(Reached, MapSize, False);
|
---|
1018 | Pile.Create(MapSize);
|
---|
1019 | Pile.Put(Loc, $800 - Movement);
|
---|
1020 | while (SlowUnloadLoc < 0) and (FastUnloadLoc < 0) and
|
---|
1021 | Pile.Get(TestLoc, TestTime) do
|
---|
1022 | begin
|
---|
1023 | Reached[TestLoc] := True;
|
---|
1024 | V8_to_Loc(TestLoc, Adjacent);
|
---|
1025 | for V8 := 0 to 7 do
|
---|
1026 | begin
|
---|
1027 | NextLoc := Adjacent[V8];
|
---|
1028 | if (NextLoc >= 0) and not Reached[NextLoc] then
|
---|
1029 | begin
|
---|
1030 | NextTile := Map[NextLoc];
|
---|
1031 | if NextTile and fTerrain = fUnknown then
|
---|
1032 | else if NextTile and fTerrain >= fGrass then
|
---|
1033 | begin
|
---|
1034 | F := Formation[NextLoc];
|
---|
1035 | if (F >= 0) and (F < maxCOD) and
|
---|
1036 | (ContinentPresence[F] and not (1 shl Me or PresenceUnknown) <> 0) and
|
---|
1037 | (NextTile and (fUnit or fOwned) <> fUnit) then
|
---|
1038 | begin
|
---|
1039 | if (nSlow > 0) and (UnitPresence[NextLoc] and
|
---|
1040 | ukSlow = 0) and ((SlowUnloadLoc < 0) or
|
---|
1041 | (Terrain[Map[NextLoc] and fTerrain].Defense >
|
---|
1042 | Terrain[Map[SlowUnloadLoc] and fTerrain].Defense)) then
|
---|
1043 | begin
|
---|
1044 | EndLoc := TestLoc;
|
---|
1045 | SlowUnloadLoc := NextLoc;
|
---|
1046 | end;
|
---|
1047 | if (nFast > 0) and (UnitPresence[NextLoc] and
|
---|
1048 | ukFast = 0) and ((FastUnloadLoc < 0) or
|
---|
1049 | (Terrain[Map[NextLoc] and fTerrain].Defense >
|
---|
1050 | Terrain[Map[FastUnloadLoc] and fTerrain].Defense)) then
|
---|
1051 | begin
|
---|
1052 | EndLoc := TestLoc;
|
---|
1053 | FastUnloadLoc := NextLoc;
|
---|
1054 | end;
|
---|
1055 | end;
|
---|
1056 | end
|
---|
1057 | else if EndLoc < 0 then
|
---|
1058 | case CheckStep(MoveStyle, TestTime, V8 and 1, NextTime,
|
---|
1059 | RecoverTurns, Map[TestLoc], NextTile, True) of
|
---|
1060 | csOk:
|
---|
1061 | Pile.Put(NextLoc, NextTime);
|
---|
1062 | csForbiddenTile:
|
---|
1063 | Reached[NextLoc] := True; // don't check moving there again
|
---|
1064 | csCheckTerritory:
|
---|
1065 | if RO.Territory[NextLoc] = RO.Territory[TestLoc] then
|
---|
1066 | Pile.Put(NextLoc, NextTime);
|
---|
1067 | end;
|
---|
1068 | end;
|
---|
1069 | end;
|
---|
1070 | end;
|
---|
1071 | Pile.Free;
|
---|
1072 |
|
---|
1073 | if EndLoc < 0 then
|
---|
1074 | Exit;
|
---|
1075 | if Loc <> EndLoc then
|
---|
1076 | Unit_MoveEx(uix, EndLoc);
|
---|
1077 | if Loc <> EndLoc then
|
---|
1078 | Exit;
|
---|
1079 | if SlowUnloadLoc >= 0 then
|
---|
1080 | begin
|
---|
1081 | Unload(ukSlow, SlowUnloadLoc);
|
---|
1082 | Dec(nSlow);
|
---|
1083 | end;
|
---|
1084 | if FastUnloadLoc >= 0 then
|
---|
1085 | begin
|
---|
1086 | Unload(ukFast, FastUnloadLoc);
|
---|
1087 | Dec(nFast);
|
---|
1088 | end;
|
---|
1089 | if TroopLoad = 0 then
|
---|
1090 | begin
|
---|
1091 | Moved[uix] := False;
|
---|
1092 | Exit;
|
---|
1093 | end
|
---|
1094 | until False;
|
---|
1095 | end;
|
---|
1096 | end;
|
---|
1097 |
|
---|
1098 | var
|
---|
1099 | uix, euix, Kind, euixBest, AttackLoc: Integer;
|
---|
1100 | OldTile: Cardinal;
|
---|
1101 | BackToStart, FirstLoop: Boolean;
|
---|
1102 | begin
|
---|
1103 | FillChar(UnitPresence, MapSize, 0);
|
---|
1104 | for uix := 0 to RO.nUn - 1 do
|
---|
1105 | with MyUnit[uix] do
|
---|
1106 | if (Loc >= 0) and (MyModel[mix].Domain = dGround) and
|
---|
1107 | (MyModel[mix].Attack > 0) then
|
---|
1108 | begin
|
---|
1109 | if MyModel[mix].Speed >= 250 then
|
---|
1110 | Kind := ukFast
|
---|
1111 | else
|
---|
1112 | Kind := ukSlow;
|
---|
1113 | UnitPresence[Loc] := UnitPresence[Loc] or Kind;
|
---|
1114 | end;
|
---|
1115 |
|
---|
1116 | FillChar(Moved, RO.nUn, False);
|
---|
1117 | for uix := 0 to RO.nUn - 1 do
|
---|
1118 | if (MyUnit[uix].Master >= 0) or (MyUnit[uix].TroopLoad > 0) then
|
---|
1119 | Moved[uix] := True;
|
---|
1120 |
|
---|
1121 | FirstLoop := True;
|
---|
1122 | repeat
|
---|
1123 | // ATTACK
|
---|
1124 | repeat
|
---|
1125 | BackToStart := False;
|
---|
1126 | if RO.nEnemyUn > 0 then
|
---|
1127 | begin
|
---|
1128 | FillChar(euixMap, MapSize * 2, $FF);
|
---|
1129 | FillChar(AttackScore, RO.nEnemyUn * 4, 0);
|
---|
1130 | for euix := 0 to RO.nEnemyUn - 1 do
|
---|
1131 | with RO.EnemyUn[euix] do
|
---|
1132 | if (Loc >= 0) and (RO.Treaty[Owner] < trPeace) then
|
---|
1133 | begin
|
---|
1134 | BackToStart := True;
|
---|
1135 | euixMap[Loc] := euix;
|
---|
1136 | uixAttack[euix] := -1;
|
---|
1137 | end;
|
---|
1138 | end;
|
---|
1139 | if not BackToStart then
|
---|
1140 | Break;
|
---|
1141 |
|
---|
1142 | for uix := 0 to RO.nUn - 1 do
|
---|
1143 | with MyUnit[uix] do
|
---|
1144 | if (Loc >= 0) and (Master < 0) and (MyModel[mix].Attack > 0) then
|
---|
1145 | RateAttack(uix);
|
---|
1146 |
|
---|
1147 | BackToStart := False;
|
---|
1148 | repeat
|
---|
1149 | euixBest := -1;
|
---|
1150 | for euix := 0 to RO.nEnemyUn - 1 do
|
---|
1151 | if (AttackScore[euix] > 0) and ((euixBest < 0) or
|
---|
1152 | (AttackScore[euix] > AttackScore[euixBest])) then
|
---|
1153 | euixBest := euix;
|
---|
1154 | if euixBest < 0 then
|
---|
1155 | Break;
|
---|
1156 | uix := uixAttack[euixBest];
|
---|
1157 | AttackLoc := RO.EnemyUn[euixBest].Loc;
|
---|
1158 | OldTile := Map[AttackLoc];
|
---|
1159 | if (AttackLoc < 0)
|
---|
1160 | // only happens when city was destroyd with attack and enemy units have disappeared
|
---|
1161 | or (DoAttack(uix, AttackLoc) and
|
---|
1162 | ((Map[AttackLoc] and fUnit <> 0) or (OldTile and fCity <> 0) and
|
---|
1163 | (Map[AttackLoc] and fCity = 0))) then
|
---|
1164 | BackToStart := True // new situation, rethink
|
---|
1165 | else
|
---|
1166 | begin
|
---|
1167 | euixMap[AttackLoc] := -1;
|
---|
1168 | AttackScore[euixBest] := 0;
|
---|
1169 | uixAttack[euixBest] := -1;
|
---|
1170 | if MyUnit[uix].Loc >= 0 then
|
---|
1171 | RateAttack(uix);
|
---|
1172 | end
|
---|
1173 | until BackToStart
|
---|
1174 | until not BackToStart;
|
---|
1175 |
|
---|
1176 | if FirstLoop then
|
---|
1177 | begin
|
---|
1178 | SetCityDefenders;
|
---|
1179 | ProcessSeaTransport;
|
---|
1180 | for uix := 0 to RO.nUn - 1 do
|
---|
1181 | with MyUnit[uix] do
|
---|
1182 | if (Loc >= 0) and (TroopLoad > 0) then
|
---|
1183 | ProcessUnload(uix);
|
---|
1184 | end;
|
---|
1185 | FirstLoop := False;
|
---|
1186 |
|
---|
1187 | for uix := 0 to RO.nUn - 1 do
|
---|
1188 | with MyUnit[uix], MyModel[mix] do
|
---|
1189 | if not Moved[uix] and (Loc >= 0) and (Domain = dSea) and
|
---|
1190 | (Attack > 0) and (Cap[mcArtillery] > 0) then
|
---|
1191 | DoAttack(uix, maNextCity); // check bombardments
|
---|
1192 |
|
---|
1193 | // MOVE
|
---|
1194 | for uix := 0 to RO.nUn - 1 do
|
---|
1195 | if not Moved[uix] then
|
---|
1196 | with MyUnit[uix] do
|
---|
1197 | if (Loc >= 0) and ((MyModel[mix].Attack > 0) or
|
---|
1198 | (MyModel[mix].Domain = dSea)) then
|
---|
1199 | if not ProcessMove(uix) then
|
---|
1200 | begin
|
---|
1201 | BackToStart := True;
|
---|
1202 | Break;
|
---|
1203 | end
|
---|
1204 | until not BackToStart;
|
---|
1205 | end;
|
---|
1206 |
|
---|
1207 | procedure TBarbarina.Barbarina_SetCityProduction;
|
---|
1208 |
|
---|
1209 | const
|
---|
1210 | CoastalWonder = 1 shl woLighthouse + 1 shl woMagellan;
|
---|
1211 | PrimeWonder = 1 shl woColossus + 1 shl woGrLibrary + 1 shl woSun +
|
---|
1212 | 1 shl woMagellan + 1 shl woEiffel + 1 shl woLiberty + 1 shl woShinkansen;
|
---|
1213 |
|
---|
1214 | function LowPriority(cix: Integer): Boolean;
|
---|
1215 | var
|
---|
1216 | part, cixHighPriority, TestDistance: Integer;
|
---|
1217 | begin
|
---|
1218 | Result := False;
|
---|
1219 | for part := 0 to nShipPart - 1 do
|
---|
1220 | begin
|
---|
1221 | cixHighPriority := ColonyShipPlan[part].cixProducing;
|
---|
1222 | if (cixHighPriority >= 0) and (cixHighPriority <> cix) then
|
---|
1223 | begin
|
---|
1224 | TestDistance := Distance(MyCity[cix].Loc, MyCity[cixHighPriority].Loc);
|
---|
1225 | if TestDistance < 11 then
|
---|
1226 | begin
|
---|
1227 | Result := True;
|
---|
1228 | Exit;
|
---|
1229 | end;
|
---|
1230 | end;
|
---|
1231 | end;
|
---|
1232 | end;
|
---|
1233 |
|
---|
1234 | function ChooseWonderToBuild(WonderAvailable: Integer; AllowCoastal: Boolean): Integer;
|
---|
1235 | var
|
---|
1236 | Count, iix: Integer;
|
---|
1237 | begin
|
---|
1238 | if (WonderAvailable and PrimeWonder > 0) and (AllowCoastal or
|
---|
1239 | (WonderAvailable and PrimeWonder and not CoastalWonder > 0)) then
|
---|
1240 | WonderAvailable := WonderAvailable and PrimeWonder; // alway prefer prime wonders
|
---|
1241 | Count := 0;
|
---|
1242 | for iix := 0 to nWonder - 1 do
|
---|
1243 | begin
|
---|
1244 | if (1 shl iix) and WonderAvailable <> 0 then
|
---|
1245 | if (1 shl iix) and CoastalWonder <> 0 then
|
---|
1246 | begin
|
---|
1247 | if AllowCoastal then
|
---|
1248 | Inc(Count, 2);
|
---|
1249 | end
|
---|
1250 | else
|
---|
1251 | Inc(Count);
|
---|
1252 | end;
|
---|
1253 | Count := Random(Count);
|
---|
1254 | for iix := 0 to nWonder - 1 do
|
---|
1255 | begin
|
---|
1256 | if (1 shl iix) and WonderAvailable <> 0 then
|
---|
1257 | if (1 shl iix) and CoastalWonder <> 0 then
|
---|
1258 | begin
|
---|
1259 | if AllowCoastal then
|
---|
1260 | Dec(Count, 2);
|
---|
1261 | end
|
---|
1262 | else
|
---|
1263 | Dec(Count);
|
---|
1264 | if Count < 0 then
|
---|
1265 | begin
|
---|
1266 | Result := iix;
|
---|
1267 | Exit;
|
---|
1268 | end;
|
---|
1269 | end;
|
---|
1270 | end;
|
---|
1271 |
|
---|
1272 | var
|
---|
1273 | I, iix, cix, mix, uix, mixProduce, mixShip, V8, V21, Loc1, TotalPop,
|
---|
1274 | AlonePop, F, f1, nTownGuard, ShipPart, ProduceShipPart, TestDistance,
|
---|
1275 | part, WonderAvailable, WonderInWork, cixNewCapital, Center, Score, BestScore: Integer;
|
---|
1276 | mixCount: array[0..nmmax - 1] of Integer;
|
---|
1277 | //RareLoc: array[0..5] of integer;
|
---|
1278 | Adjacent: TVicinity8Loc;
|
---|
1279 | IsCoastal, IsPort, IsUnitProjectObsolete, HasSettler, SpezializeShipProduction,
|
---|
1280 | AlgaeAvailable, ProjectComplete, DoLowPriority, WillProduceColonyShip,
|
---|
1281 | ImportantCity: Boolean;
|
---|
1282 | Radius: TVicinity21Loc;
|
---|
1283 | Report: TCityReportNew;
|
---|
1284 | begin
|
---|
1285 | AnalyzeMap;
|
---|
1286 |
|
---|
1287 | FindBestModels;
|
---|
1288 |
|
---|
1289 | FillChar(mixCount, RO.nModel * 4, 0);
|
---|
1290 | for uix := 0 to RO.nUn - 1 do
|
---|
1291 | with MyUnit[uix] do
|
---|
1292 | if Loc >= 0 then
|
---|
1293 | Inc(mixCount[mix]);
|
---|
1294 | if (mixBest[ctGroundSlow] >= 0) and ((mixBest[ctGroundFast] < 0) or
|
---|
1295 | (mixCount[mixBest[ctGroundSlow]] < mixCount[mixBest[ctGroundFast]])) then
|
---|
1296 | mixProduce := mixBest[ctGroundSlow]
|
---|
1297 | else
|
---|
1298 | mixProduce := mixBest[ctGroundFast];
|
---|
1299 | if (mixBest[ctSeaTrans] >= 0) and ((mixBest[ctSeaArt] < 0) or
|
---|
1300 | (mixCount[mixBest[ctSeaTrans]] < mixCount[mixBest[ctSeaArt]])) then
|
---|
1301 | mixShip := mixBest[ctSeaTrans]
|
---|
1302 | else
|
---|
1303 | mixShip := mixBest[ctSeaArt];
|
---|
1304 | if (mixProduce >= 0) and (mixBest[ctSeaTrans] >= 0) and
|
---|
1305 | (mixCount[mixShip] * RO.Model[mixBest[ctSeaTrans]].Cap[mcSeaTrans] *
|
---|
1306 | RO.Model[mixBest[ctSeaTrans]].MTrans div 2 >= mixCount[mixProduce]) then
|
---|
1307 | mixShip := -1;
|
---|
1308 |
|
---|
1309 | // produce ships only on certain continents?
|
---|
1310 | TotalPop := 0;
|
---|
1311 | AlonePop := 0;
|
---|
1312 | for cix := 0 to RO.nCity - 1 do
|
---|
1313 | with MyCity[cix] do
|
---|
1314 | if (Loc >= 0) and (Flags and chCaptured = 0) then
|
---|
1315 | begin
|
---|
1316 | Inc(TotalPop, Size);
|
---|
1317 | F := Formation[Loc];
|
---|
1318 | if (F < 0) or (F >= maxCOD) or (ContinentPresence[F] = 1 shl Me) then
|
---|
1319 | Inc(AlonePop, Size);
|
---|
1320 | end;
|
---|
1321 | SpezializeShipProduction := AlonePop * 2 >= TotalPop;
|
---|
1322 |
|
---|
1323 | cixNewCapital := -1;
|
---|
1324 | WonderAvailable := 0;
|
---|
1325 | WonderInWork := 0;
|
---|
1326 | for iix := 0 to nWonder - 1 do
|
---|
1327 | if (Imp[iix].Preq <> preNA) and ((Imp[iix].Preq = preNone) or
|
---|
1328 | IsResearched(Imp[iix].Preq)) and (RO.Wonder[iix].CityID = WonderNotBuiltYet) then
|
---|
1329 | Inc(WonderAvailable, 1 shl iix);
|
---|
1330 | for cix := 0 to RO.nCity - 1 do
|
---|
1331 | if MyCity[cix].Loc >= 0 then
|
---|
1332 | begin
|
---|
1333 | iix := City_CurrentImprovementProject(cix);
|
---|
1334 | if (iix >= 0) and (iix < nWonder) then
|
---|
1335 | Inc(WonderInWork, 1 shl iix)
|
---|
1336 | else if iix = imPalace then
|
---|
1337 | cixNewCapital := cix;
|
---|
1338 | end;
|
---|
1339 |
|
---|
1340 | if (RO.NatBuilt[imPalace] = 0) and (cixNewCapital < 0) then
|
---|
1341 | begin // palace was destroyed, build new one
|
---|
1342 | Center := CenterOfEmpire;
|
---|
1343 | BestScore := 0;
|
---|
1344 | for cix := 0 to RO.nCity - 1 do
|
---|
1345 | with MyCity[cix] do
|
---|
1346 | if (Loc >= 0) and (Flags and chCaptured = 0) then
|
---|
1347 | begin // evaluate city as new capital
|
---|
1348 | Score := Size * 12 + 512 - Distance(Loc, Center);
|
---|
1349 | V8_to_Loc(Loc, Adjacent);
|
---|
1350 | for V8 := 0 to 7 do
|
---|
1351 | begin
|
---|
1352 | Loc1 := Adjacent[V8];
|
---|
1353 | if (Loc1 >= 0) and (Map[Loc1] and fTerrain < fGrass) then
|
---|
1354 | begin
|
---|
1355 | f1 := Formation[Loc1];
|
---|
1356 | if (f1 >= 0) and (f1 < maxCOD) and
|
---|
1357 | ((OceanSize[f1] >= 8) or (OceanPresence[f1] and not
|
---|
1358 | (1 shl Me) <> 0)) then
|
---|
1359 | begin // prefer non-coastal cities
|
---|
1360 | Dec(Score, 18);
|
---|
1361 | Break;
|
---|
1362 | end;
|
---|
1363 | end;
|
---|
1364 | end;
|
---|
1365 | if Score > BestScore then
|
---|
1366 | begin
|
---|
1367 | BestScore := Score;
|
---|
1368 | cixNewCapital := cix;
|
---|
1369 | end;
|
---|
1370 | end;
|
---|
1371 | end;
|
---|
1372 |
|
---|
1373 | AlgaeAvailable := (RO.NatBuilt[imAlgae] = 0) and
|
---|
1374 | (RO.Tech[Imp[imAlgae].Preq] >= tsApplicable);
|
---|
1375 | for cix := 0 to RO.nCity - 1 do
|
---|
1376 | with MyCity[cix] do
|
---|
1377 | if (Loc >= 0) and (Project and (cpImp + cpIndex) = cpImp + imAlgae) then
|
---|
1378 | AlgaeAvailable := False;
|
---|
1379 |
|
---|
1380 | for cix := 0 to RO.nCity - 1 do
|
---|
1381 | with MyCity[cix] do
|
---|
1382 | if (Loc >= 0) and (Flags and chCaptured = 0) and LowPriority(cix) then
|
---|
1383 | City_SetTiles(cix, 1 shl CityOwnTile); // free all tiles of low-prio cities
|
---|
1384 | for DoLowPriority := False to True do
|
---|
1385 | for cix := 0 to RO.nCity - 1 do
|
---|
1386 | with MyCity[cix] do
|
---|
1387 | if (Loc >= 0) and (Flags and chCaptured = 0) and
|
---|
1388 | (LowPriority(cix) = DoLowPriority) then
|
---|
1389 | begin
|
---|
1390 | F := Formation[Loc];
|
---|
1391 | IsCoastal := False;
|
---|
1392 | IsPort := False;
|
---|
1393 | V8_to_Loc(Loc, Adjacent);
|
---|
1394 | for V8 := 0 to 7 do
|
---|
1395 | begin
|
---|
1396 | Loc1 := Adjacent[V8];
|
---|
1397 | if (Loc1 >= 0) and (Map[Loc1] and fTerrain < fGrass) then
|
---|
1398 | begin
|
---|
1399 | IsCoastal := True;
|
---|
1400 | f1 := Formation[Loc1];
|
---|
1401 | if (f1 >= 0) and (f1 < maxCOD) and (OceanSize[f1] >= 8) and
|
---|
1402 | (OceanPresence[f1] and not (1 shl Me) <> 0) then
|
---|
1403 | begin
|
---|
1404 | IsPort := True;
|
---|
1405 | Break;
|
---|
1406 | end;
|
---|
1407 | end;
|
---|
1408 | end;
|
---|
1409 | if (City_CurrentUnitProject(cix) >= 0) and
|
---|
1410 | (RO.Model[City_CurrentUnitProject(cix)].Kind <> mkSettler) then
|
---|
1411 | begin
|
---|
1412 | I := nModelCategory - 1;
|
---|
1413 | while (I >= 0) and (City_CurrentUnitProject(cix) <> mixBest[I]) do
|
---|
1414 | Dec(I);
|
---|
1415 | IsUnitProjectObsolete := I < 0;
|
---|
1416 | end
|
---|
1417 | else
|
---|
1418 | IsUnitProjectObsolete := False;
|
---|
1419 | if RO.Government = gDespotism then
|
---|
1420 | begin
|
---|
1421 | nTownGuard := 0;
|
---|
1422 | for uix := 0 to RO.nUn - 1 do
|
---|
1423 | if (MyUnit[uix].mix = mixTownGuard) and (MyUnit[uix].Loc = Loc) then
|
---|
1424 | Inc(nTownGuard);
|
---|
1425 | end;
|
---|
1426 |
|
---|
1427 | iix := City_CurrentImprovementProject(cix);
|
---|
1428 | if (iix >= 0) and (iix < nWonder) or (iix = imPalace) or
|
---|
1429 | (iix = imShipComp) or (iix = imShipPow) or (iix = imShipHab) then
|
---|
1430 | City_OptimizeTiles(cix, rwMaxProd)
|
---|
1431 | else if Size < 8 then
|
---|
1432 | City_OptimizeTiles(cix, rwMaxGrowth)
|
---|
1433 | else
|
---|
1434 | City_OptimizeTiles(cix, rwForceProd);
|
---|
1435 |
|
---|
1436 | WillProduceColonyShip := False;
|
---|
1437 | ProduceShipPart := -1;
|
---|
1438 | for part := 0 to nShipPart - 1 do
|
---|
1439 | if ColonyShipPlan[part].cixProducing = cix then
|
---|
1440 | begin
|
---|
1441 | WillProduceColonyShip := True;
|
---|
1442 | ProduceShipPart := ShipImpIndex[part];
|
---|
1443 | end;
|
---|
1444 |
|
---|
1445 | if cix = cixNewCapital then
|
---|
1446 | City_StartImprovement(cix, imPalace)
|
---|
1447 | else if (iix >= 0) and (iix < nWonder) and ((1 shl iix) and
|
---|
1448 | WonderAvailable <> 0) then
|
---|
1449 | // complete wonder production first
|
---|
1450 | else if (mixProduce >= 0) and (City_CurrentUnitProject(cix) >= 0) and
|
---|
1451 | not IsUnitProjectObsolete and ((Flags and chProduction = 0) or
|
---|
1452 | (RO.Model[City_CurrentUnitProject(cix)].Cap[mcLine] > 0) and
|
---|
1453 | (mixCount[City_CurrentUnitProject(cix)] < RO.nCity * (2 + cix and 3))) then
|
---|
1454 | // complete unit production first
|
---|
1455 | else
|
---|
1456 | begin
|
---|
1457 | if ProduceShipPart >= 0 then
|
---|
1458 | begin
|
---|
1459 | if (Built[imGranary] = 0) and (Size < 10) and
|
---|
1460 | City_Improvable(cix, imGranary) then
|
---|
1461 | City_StartImprovement(cix, imGranary)
|
---|
1462 | else if (Built[imAqueduct] = 0) and City_Improvable(cix, imAqueduct) then
|
---|
1463 | City_StartImprovement(cix, imAqueduct)
|
---|
1464 | else if (Built[imAqueduct] > 0) and (Size < 12) and
|
---|
1465 | (AlgaeAvailable or (Project and (cpImp + cpIndex) =
|
---|
1466 | cpImp + imAlgae)) then
|
---|
1467 | City_StartImprovement(cix, imAlgae)
|
---|
1468 | else if (Built[imFactory] = 0) and City_Improvable(cix, imFactory) then
|
---|
1469 | City_StartImprovement(cix, imFactory)
|
---|
1470 | else if (Built[imPower] + Built[imHydro] + Built[imNuclear] = 0) and
|
---|
1471 | (City_Improvable(cix, imPower) or
|
---|
1472 | City_Improvable(cix, imHydro) or City_Improvable(cix, imNuclear)) then
|
---|
1473 | begin
|
---|
1474 | if City_Improvable(cix, imHydro) then
|
---|
1475 | City_StartImprovement(cix, imHydro)
|
---|
1476 | else if City_Improvable(cix, imPower) then
|
---|
1477 | City_StartImprovement(cix, imPower)
|
---|
1478 | else
|
---|
1479 | City_StartImprovement(cix, imNuclear);
|
---|
1480 | end
|
---|
1481 | else if (Built[imMfgPlant] = 0) and City_Improvable(cix, imMfgPlant) then
|
---|
1482 | City_StartImprovement(cix, imMfgPlant)
|
---|
1483 | else if City_Improvable(cix, ProduceShipPart) then
|
---|
1484 | City_StartImprovement(cix, ProduceShipPart)
|
---|
1485 | else
|
---|
1486 | ProduceShipPart := -1;
|
---|
1487 | end;
|
---|
1488 | if ProduceShipPart < 0 then
|
---|
1489 | begin
|
---|
1490 | ProjectComplete :=
|
---|
1491 | not City_HasProject(cix) or (Flags and chProduction <> 0);
|
---|
1492 | HasSettler := False;
|
---|
1493 | for uix := 0 to RO.nUn - 1 do
|
---|
1494 | with MyUnit[uix] do
|
---|
1495 | if (Loc >= 0) and (Home = cix) and
|
---|
1496 | (MyModel[mix].Kind = mkSettler) then
|
---|
1497 | HasSettler := True;
|
---|
1498 | if ((RO.Government <> gDespotism) or (RO.nUn >= RO.nCity * 4)) and
|
---|
1499 | not IsResearched(adMassProduction) and (Built[imPalace] > 0) and
|
---|
1500 | (RO.Wonder[woZeus].CityID = WonderNotBuiltYet) and City_Improvable(cix, woZeus) then
|
---|
1501 | City_StartImprovement(cix, woZeus)
|
---|
1502 | else if (City_CurrentImprovementProject(cix) >= 0) and
|
---|
1503 | (City_CurrentImprovementProject(cix) < nWonder) then
|
---|
1504 | begin// wonder already built, try to switch to different one
|
---|
1505 | if (WonderAvailable and not WonderInWork > 0) and
|
---|
1506 | (IsCoastal or (WonderAvailable and not WonderInWork and
|
---|
1507 | not CoastalWonder > 0)) then
|
---|
1508 | begin
|
---|
1509 | iix := ChooseWonderToBuild(WonderAvailable and not
|
---|
1510 | WonderInWork, IsCoastal);
|
---|
1511 | City_StartImprovement(cix, iix);
|
---|
1512 | WonderInWork := WonderInWork or (1 shl iix);
|
---|
1513 | end
|
---|
1514 | else
|
---|
1515 | City_StopProduction(cix);
|
---|
1516 | end
|
---|
1517 | else if (Built[imPalace] > 0) and (RO.NatBuilt[imSpacePort] = 0) and
|
---|
1518 | City_Improvable(cix, imSpacePort) then
|
---|
1519 | City_StartImprovement(cix, imSpacePort)
|
---|
1520 | else if Built[imPalace] + Built[imCourt] + Built[imTownHall] = 0 then
|
---|
1521 | begin
|
---|
1522 | if City_Improvable(cix, imCourt) then
|
---|
1523 | City_StartImprovement(cix, imCourt)
|
---|
1524 | else
|
---|
1525 | City_StartImprovement(cix, imTownHall);
|
---|
1526 | end
|
---|
1527 | else if not HasSettler and (RO.nUn >= RO.nCity * 4) then
|
---|
1528 | begin
|
---|
1529 | if ProjectComplete and (City_CurrentUnitProject(cix) <> 0) then
|
---|
1530 | begin
|
---|
1531 | mix := RO.nModel - 1;
|
---|
1532 | while RO.Model[mix].Kind <> mkSettler do
|
---|
1533 | Dec(mix);
|
---|
1534 | City_StartUnitProduction(cix, mix);
|
---|
1535 | end;
|
---|
1536 | end
|
---|
1537 | else if (RO.Government = gDespotism) and (nTownGuard < 2) and
|
---|
1538 | (nTownGuard * 2 + 3 < Size) then
|
---|
1539 | begin
|
---|
1540 | if ProjectComplete then
|
---|
1541 | City_StartUnitProduction(cix, 2);
|
---|
1542 | end
|
---|
1543 | else if (RO.Government = gFundamentalism) and
|
---|
1544 | (Size >= 8) and (Built[imAqueduct] = 0) and
|
---|
1545 | City_Improvable(cix, imAqueduct) and (RO.nUn >= RO.nCity * 4) then
|
---|
1546 | begin
|
---|
1547 | if ProjectComplete then
|
---|
1548 | City_StartImprovement(cix, imAqueduct);
|
---|
1549 | end
|
---|
1550 | else if ProjectComplete then
|
---|
1551 | begin // low prio projects
|
---|
1552 | ImportantCity := WillProduceColonyShip or (Built[imPalace] > 0);
|
---|
1553 | for iix := 0 to nWonder - 1 do
|
---|
1554 | if Built[iix] > 0 then
|
---|
1555 | ImportantCity := True;
|
---|
1556 | City_GetReportNew(cix, Report);
|
---|
1557 | if (Report.Corruption >= 6) and (RO.nUn >= RO.nCity * 4) and
|
---|
1558 | City_Improvable(cix, imCourt) then
|
---|
1559 | City_StartImprovement(cix, imCourt)
|
---|
1560 | else if (Report.Production >= WonderProductionThreshold) and
|
---|
1561 | (WonderAvailable and not WonderInWork > 0) and
|
---|
1562 | (IsCoastal or (WonderAvailable and not WonderInWork and
|
---|
1563 | not CoastalWonder > 0)) and (Random >=
|
---|
1564 | (1 + WonderInclination) / (RO.nCity + WonderInclination)) then
|
---|
1565 | begin
|
---|
1566 | iix := ChooseWonderToBuild(WonderAvailable and not
|
---|
1567 | WonderInWork, IsCoastal);
|
---|
1568 | City_StartImprovement(cix, iix);
|
---|
1569 | WonderInWork := WonderInWork or (1 shl iix);
|
---|
1570 | end
|
---|
1571 | else if (ImportantCity or (Loc mod 9 = 0)) and
|
---|
1572 | (Built[imWalls] = 0) and City_Improvable(cix, imWalls) then
|
---|
1573 | City_StartImprovement(cix, imWalls)
|
---|
1574 | else if IsPort and (ImportantCity or (Loc mod 7 = 0)) and
|
---|
1575 | (Built[imCoastalFort] = 0) and City_Improvable(cix, imCoastalFort) then
|
---|
1576 | City_StartImprovement(cix, imCoastalFort)
|
---|
1577 | {else if (ImportantCity or (Loc mod 11=0)) and (Built[imMissileBat]=0)
|
---|
1578 | and City_Improvable(cix,imMissileBat) then
|
---|
1579 | City_StartImprovement(cix,imMissileBat)}
|
---|
1580 | else if IsPort and (not SpezializeShipProduction or
|
---|
1581 | (F < 0) or (F >= maxCOD) or (ContinentPresence[F] = 1 shl Me)) and
|
---|
1582 | (Built[imDockyard] = 0) and City_Improvable(cix, imDockyard) then
|
---|
1583 | City_StartImprovement(cix, imDockyard)
|
---|
1584 | else if IsPort and (mixShip >= 0) and
|
---|
1585 | (not SpezializeShipProduction or (F < 0) or
|
---|
1586 | (F >= maxCOD) or (ContinentPresence[F] = 1 shl Me)) then
|
---|
1587 | City_StartUnitProduction(cix, mixShip)
|
---|
1588 | else if (Built[imBarracks] + Built[imMilAcademy] = 0) and
|
---|
1589 | City_Improvable(cix, imBarracks) then
|
---|
1590 | City_StartImprovement(cix, imBarracks)
|
---|
1591 | else if mixProduce >= 0 then
|
---|
1592 | City_StartUnitProduction(cix, mixProduce)
|
---|
1593 | else if City_HasProject(cix) then
|
---|
1594 | City_StopProduction(cix);
|
---|
1595 | end;
|
---|
1596 | end;
|
---|
1597 | end;
|
---|
1598 | if (City_CurrentImprovementProject(cix) = imCourt) and
|
---|
1599 | (Built[imTownHall] > 0) and (Prod >= imp[imCourt].Cost *
|
---|
1600 | BuildCostMod[G.Difficulty[Me]] div 12 -
|
---|
1601 | (Imp[imTownHall].Cost * BuildCostMod[G.Difficulty[Me]] div 12) *
|
---|
1602 | 2 div 3) then
|
---|
1603 | City_RebuildImprovement(cix, imTownHall)
|
---|
1604 | else if (RO.Government = gFundamentalism) and not WillProduceColonyShip then
|
---|
1605 | for iix := nWonder to nImp - 1 do
|
---|
1606 | if (Built[iix] > 0) and
|
---|
1607 | ((iix in [imTemple, imTheater, imCathedral, imColosseum,
|
---|
1608 | imLibrary, imUniversity, imResLab, imHarbor, imSuperMarket]) or
|
---|
1609 | (iix in [imFactory, imMfgPlant, imPower, imHydro, imNuclear]) and
|
---|
1610 | (Built[imRecycling] = 0)) then
|
---|
1611 | begin
|
---|
1612 | if City_RebuildImprovement(cix, iix) < rExecuted then
|
---|
1613 | City_SellImprovement(cix, iix);
|
---|
1614 | Break;
|
---|
1615 | end;
|
---|
1616 | end;
|
---|
1617 | end;
|
---|
1618 |
|
---|
1619 | function TBarbarina.Barbarina_ChooseResearchAdvance: Integer;
|
---|
1620 | var
|
---|
1621 | nPreq, rmix, rmixChosen, I, MaxWeight, MaxDefense, ChosenPreq: Integer;
|
---|
1622 | NeedSeaUnits, Ready: Boolean;
|
---|
1623 | ModelExists: set of 0..nModelCategory - 1;
|
---|
1624 | Known: array[0..nAdv - 1] of Integer;
|
---|
1625 |
|
---|
1626 | procedure ChoosePreq(ad: Integer);
|
---|
1627 | var
|
---|
1628 | I: Integer;
|
---|
1629 | PreqOk: Boolean;
|
---|
1630 | begin
|
---|
1631 | Assert(RO.Tech[ad] < tsApplicable);
|
---|
1632 | if Known[ad] = 0 then
|
---|
1633 | begin
|
---|
1634 | Known[ad] := 1;
|
---|
1635 | PreqOk := True;
|
---|
1636 | if not (ad in [adScience, adMassProduction]) and (RO.Tech[ad] < tsSeen) then
|
---|
1637 | for I := 0 to 1 do
|
---|
1638 | if (AdvPreq[ad, I] >= 0) and (RO.Tech[AdvPreq[ad, I]] < tsApplicable) then
|
---|
1639 | begin
|
---|
1640 | PreqOk := False;
|
---|
1641 | ChoosePreq(AdvPreq[ad, I]);
|
---|
1642 | end;
|
---|
1643 | if PreqOk then
|
---|
1644 | begin
|
---|
1645 | Inc(nPreq);
|
---|
1646 | if Random(nPreq) = 0 then
|
---|
1647 | ChosenPreq := ad;
|
---|
1648 | end;
|
---|
1649 | end;
|
---|
1650 | end;
|
---|
1651 |
|
---|
1652 | begin
|
---|
1653 | // check military research
|
---|
1654 | rmixChosen := -1;
|
---|
1655 | ModelExists := [];
|
---|
1656 | for rmix := nResearchModel - 1 downto 0 do
|
---|
1657 | with ResearchModel[rmix] do
|
---|
1658 | if not (Category in ModelExists) and ((adStop < 0) or not
|
---|
1659 | IsResearched(adStop)) then
|
---|
1660 | begin
|
---|
1661 | MaxWeight := 0;
|
---|
1662 | case Domain of
|
---|
1663 | dGround:
|
---|
1664 | begin
|
---|
1665 | if IsResearched(adWarriorCode) then
|
---|
1666 | MaxWeight := 5;
|
---|
1667 | if IsResearched(adHorsebackRiding) then
|
---|
1668 | MaxWeight := 7;
|
---|
1669 | if IsResearched(adAutomobile) then
|
---|
1670 | MaxWeight := 10;
|
---|
1671 | end;
|
---|
1672 | dSea:
|
---|
1673 | begin
|
---|
1674 | if IsResearched(adMapMaking) then
|
---|
1675 | MaxWeight := 5;
|
---|
1676 | if IsResearched(adSeaFaring) then
|
---|
1677 | MaxWeight := 7;
|
---|
1678 | if IsResearched(adSteel) then
|
---|
1679 | MaxWeight := 9;
|
---|
1680 | end;
|
---|
1681 | dAir:
|
---|
1682 | begin
|
---|
1683 | if IsResearched(adFlight) then
|
---|
1684 | MaxWeight := 5;
|
---|
1685 | if IsResearched(adAdvancedFlight) then
|
---|
1686 | MaxWeight := 7;
|
---|
1687 | end;
|
---|
1688 | end;
|
---|
1689 | if Domain = dGround then
|
---|
1690 | MaxDefense := 2
|
---|
1691 | else
|
---|
1692 | MaxDefense := 3;
|
---|
1693 | if IsResearched(adSteel) then
|
---|
1694 | Inc(MaxDefense);
|
---|
1695 | Ready := (MaxWeight >= Weight) and (MaxDefense >= Cap[mcDefense]);
|
---|
1696 | if Ready then
|
---|
1697 | for I := 0 to nFeature - 1 do
|
---|
1698 | if (Cap[I] > 0) and (Feature[I].Preq <> preNone) and
|
---|
1699 | ((Feature[I].Preq < 0) or not IsResearched(Feature[I].Preq)) then
|
---|
1700 | Ready := False;
|
---|
1701 | if Ready then
|
---|
1702 | begin
|
---|
1703 | for I := 0 to nUpgrade - 1 do
|
---|
1704 | if (Upgrades and (1 shl I) <> 0) and not
|
---|
1705 | IsResearched(Upgrade[Domain, I].Preq) then
|
---|
1706 | Ready := False;
|
---|
1707 | end;
|
---|
1708 | if Ready then
|
---|
1709 | begin
|
---|
1710 | Include(ModelExists, Category);
|
---|
1711 | if not IsModelAvailable(rmix) then
|
---|
1712 | rmixChosen := rmix;
|
---|
1713 | end;
|
---|
1714 | end;
|
---|
1715 | if rmixChosen >= 0 then
|
---|
1716 | with ResearchModel[rmixChosen] do
|
---|
1717 | begin
|
---|
1718 | PrepareNewModel(Domain);
|
---|
1719 | for I := 0 to nFeature - 1 do
|
---|
1720 | if (I < 2) or (Cap[I] > 0) then
|
---|
1721 | SetNewModelFeature(I, Cap[I]);
|
---|
1722 | if RO.Wonder[woSun].EffectiveOwner = Me then
|
---|
1723 | begin
|
---|
1724 | //if Cap[mcWeapons]>=2*Cap[mcArmor] then
|
---|
1725 | // SetNewModelFeature(mcFirst,1);
|
---|
1726 | if Cap[mcWeapons] >= Cap[mcArmor] then
|
---|
1727 | SetNewModelFeature(mcWill, 1);
|
---|
1728 | end;
|
---|
1729 | Result := adMilitary;
|
---|
1730 | Exit;
|
---|
1731 | end;
|
---|
1732 |
|
---|
1733 | NeedSeaUnits := True;
|
---|
1734 | I := 0;
|
---|
1735 | while (I < nResearchOrder) and (not NeedSeaUnits and (ResearchOrder[I] < 0) or
|
---|
1736 | IsResearched(Abs(ResearchOrder[I]))) do
|
---|
1737 | Inc(I);
|
---|
1738 | if I >= nResearchOrder then // list done, continue with future tech
|
---|
1739 | begin
|
---|
1740 | if Random(2) = 1 then
|
---|
1741 | Result := futArtificialIntelligence
|
---|
1742 | else
|
---|
1743 | Result := futMaterialTechnology;
|
---|
1744 | end
|
---|
1745 | else
|
---|
1746 | begin
|
---|
1747 | FillChar(Known, SizeOf(Known), 0);
|
---|
1748 | nPreq := 0;
|
---|
1749 | ChosenPreq := -1;
|
---|
1750 | ChoosePreq(Abs(ResearchOrder[I]));
|
---|
1751 | Assert(nPreq > 0);
|
---|
1752 | Result := ChosenPreq;
|
---|
1753 | end;
|
---|
1754 | end;
|
---|
1755 |
|
---|
1756 | function TBarbarina.Barbarina_WantCheckNegotiation(Nation: Integer): Boolean;
|
---|
1757 | begin
|
---|
1758 | if (RO.Tech[adTheRepublic] < tsSeen) and (RO.Tech[adTheology] >= tsApplicable) and
|
---|
1759 | (RO.Tech[adGunPowder] >= tsApplicable) and
|
---|
1760 | (RO.EnemyReport[Nation].Tech[adTheRepublic] >= tsApplicable) then
|
---|
1761 | Result := True
|
---|
1762 | else
|
---|
1763 | Result := False;
|
---|
1764 | end;
|
---|
1765 |
|
---|
1766 | procedure TBarbarina.Barbarina_DoCheckNegotiation;
|
---|
1767 | begin
|
---|
1768 | if RO.Tech[adTheRepublic] >= tsSeen then
|
---|
1769 | Exit; // default reaction
|
---|
1770 | if MyLastAction = scContact then
|
---|
1771 | begin
|
---|
1772 | MyAction := scDipOffer;
|
---|
1773 | MyOffer.nDeliver := 1;
|
---|
1774 | MyOffer.nCost := 1;
|
---|
1775 | if (RO.Tech[adTheology] >= tsApplicable) and
|
---|
1776 | (RO.EnemyReport[Opponent].Tech[adTheology] < tsSeen) then
|
---|
1777 | MyOffer.Price[0] := opTech + adTheology
|
---|
1778 | else
|
---|
1779 | MyOffer.Price[0] := opChoose;
|
---|
1780 | MyOffer.Price[1] := opTech + adTheRepublic;
|
---|
1781 | end
|
---|
1782 | else if OppoAction = scDipAccept then
|
---|
1783 | else if OppoAction = scDipOffer then
|
---|
1784 | begin
|
---|
1785 | if (OppoOffer.nDeliver = 1) and (OppoOffer.Price[0] = opTech + adTheRepublic) and
|
---|
1786 | ((OppoOffer.nCost = 0) or (OppoOffer.nCost = 1) and
|
---|
1787 | (OppoOffer.Price[1] and opMask = opTech) and
|
---|
1788 | (RO.Tech[OppoOffer.Price[1] - opTech] >= tsApplicable)) then
|
---|
1789 | MyAction := scDipAccept
|
---|
1790 | else
|
---|
1791 | MyAction := scDipBreak;
|
---|
1792 | end
|
---|
1793 | else if OppoAction <> scDipBreak then
|
---|
1794 | MyAction := scDipBreak;
|
---|
1795 | end;
|
---|
1796 |
|
---|
1797 | function TBarbarina.Barbarina_WantNegotiation(Nation: Integer;
|
---|
1798 | NegoTime: TNegoTime): Boolean;
|
---|
1799 | var
|
---|
1800 | uix, TestLoc, V8: Integer;
|
---|
1801 | Adjacent: TVicinity8Loc;
|
---|
1802 | begin
|
---|
1803 | Result := False;
|
---|
1804 | case NegoTime of
|
---|
1805 | EnemyCalled:
|
---|
1806 | Result := False;
|
---|
1807 | EndOfTurn:
|
---|
1808 | Result := False;
|
---|
1809 | BeginOfTurn:
|
---|
1810 | if RO.Turn >= RO.LastCancelTreaty[Nation] + CancelTreatyTurns then
|
---|
1811 | begin
|
---|
1812 | if (RO.Turn and 3 = (Nation + $F - Me) and 3) and
|
---|
1813 | (RO.Treaty[Nation] > trPeace) then
|
---|
1814 | begin
|
---|
1815 | DebugMessage(1, 'End alliance/friendly contact with P' + char(48 + Nation));
|
---|
1816 | NegoCause := CancelTreaty;
|
---|
1817 | Result := True;
|
---|
1818 | end
|
---|
1819 | else if RO.Treaty[Nation] = trPeace then
|
---|
1820 | begin // declare war now?
|
---|
1821 | for uix := 0 to RO.nUn - 1 do
|
---|
1822 | with MyUnit[uix] do
|
---|
1823 | if (Loc >= 0) and (MyModel[mix].Attack > 0) then
|
---|
1824 | begin
|
---|
1825 | V8_to_Loc(Loc, Adjacent);
|
---|
1826 | for V8 := 0 to 7 do
|
---|
1827 | begin
|
---|
1828 | TestLoc := Adjacent[V8];
|
---|
1829 | if (TestLoc >= 0) and (RO.Territory[TestLoc] = Nation) and
|
---|
1830 | ((Map[TestLoc] and fTerrain >= fGrass) or
|
---|
1831 | (Master >= 0) or (MyModel[mix].Domain <> dGround)) and
|
---|
1832 | ((Map[TestLoc] and fTerrain < fGrass) or
|
---|
1833 | (MyModel[mix].Domain <> dSea)) then
|
---|
1834 | begin
|
---|
1835 | DebugMessage(1, 'Declare war on P' + Char(48 + Nation));
|
---|
1836 | NegoCause := CancelTreaty;
|
---|
1837 | Result := True;
|
---|
1838 | Exit;
|
---|
1839 | end;
|
---|
1840 | end;
|
---|
1841 | end;
|
---|
1842 | end;
|
---|
1843 | end;
|
---|
1844 | end;
|
---|
1845 | end;
|
---|
1846 |
|
---|
1847 | procedure TBarbarina.Barbarina_DoNegotiation;
|
---|
1848 | begin
|
---|
1849 | if OppoAction = scDipStart then
|
---|
1850 | begin
|
---|
1851 | if NegoCause = CancelTreaty then
|
---|
1852 | MyAction := scDipCancelTreaty;
|
---|
1853 | end;
|
---|
1854 | end;
|
---|
1855 |
|
---|
1856 | procedure TBarbarina.MakeColonyShipPlan;
|
---|
1857 | var
|
---|
1858 | I, V21, V21C, CityLoc, Loc1, Part, cix, BestValue, TestValue, FoodCount,
|
---|
1859 | ProdCount, ProdExtra, Score, BestScore: Integer;
|
---|
1860 | Tile: Cardinal;
|
---|
1861 | Ok, Check: Boolean;
|
---|
1862 | Radius, RadiusC: TVicinity21Loc;
|
---|
1863 | begin
|
---|
1864 | for Part := 0 to nShipPart - 1 do
|
---|
1865 | begin
|
---|
1866 | ColonyShipPlan[Part].cixProducing := -1;
|
---|
1867 | ColonyShipPlan[Part].nLocResource := 0;
|
---|
1868 | ColonyShipPlan[Part].nLocFoundCity := 0;
|
---|
1869 | end;
|
---|
1870 | if RO.Tech[adMassProduction] >= tsApplicable then // able to recognize ressources yet
|
---|
1871 | begin
|
---|
1872 | // Check already existing cities
|
---|
1873 | for cix := 0 to RO.nCity - 1 do
|
---|
1874 | with MyCity[cix] do
|
---|
1875 | if Loc >= 0 then
|
---|
1876 | begin
|
---|
1877 | V21_to_Loc(Loc, Radius);
|
---|
1878 | for V21 := 1 to 26 do
|
---|
1879 | begin
|
---|
1880 | Loc1 := Radius[V21];
|
---|
1881 | if Loc1 >= 0 then
|
---|
1882 | begin
|
---|
1883 | Tile := RO.Map[Loc1];
|
---|
1884 | if Tile and fModern <> 0 then
|
---|
1885 | begin
|
---|
1886 | Part := (Tile and fModern) shr 25 - 1;
|
---|
1887 | if RO.Ship[Me].Parts[Part] < ShipNeed[Part] then
|
---|
1888 | // not enough of this kind already
|
---|
1889 | begin
|
---|
1890 | Ok := True;
|
---|
1891 | if ColonyShipPlan[Part].cixProducing >= 0 then
|
---|
1892 | begin // another city is already assigned to this ship part, choose one of the two
|
---|
1893 | TestValue := (ID and $FFF) shl 4 + ((ID shr 12) + 15 - Me) and $F;
|
---|
1894 | BestValue :=
|
---|
1895 | (MyCity[ColonyShipPlan[Part].cixProducing].ID and $FFF) shl
|
---|
1896 | 4 + ((MyCity[ColonyShipPlan[Part].cixProducing].ID shr 12) +
|
---|
1897 | 15 - Me) and $F;
|
---|
1898 | if TestValue <= BestValue then
|
---|
1899 | Ok := False;
|
---|
1900 | end;
|
---|
1901 | if Ok then
|
---|
1902 | ColonyShipPlan[part].cixProducing := cix;
|
---|
1903 | end;
|
---|
1904 | end;
|
---|
1905 | end;
|
---|
1906 | end;
|
---|
1907 | end;
|
---|
1908 |
|
---|
1909 | // for parts without existing city, look for location of city to found
|
---|
1910 | Check := False;
|
---|
1911 | for Part := 0 to nShipPart - 1 do
|
---|
1912 | if (RO.Ship[Me].Parts[Part] < ShipNeed[Part]) // not enough of this kind already
|
---|
1913 | and (ColonyShipPlan[Part].cixProducing < 0) then // no city to produce
|
---|
1914 | Check := True;
|
---|
1915 | if Check then
|
---|
1916 | begin
|
---|
1917 | for Loc1 := 0 to MapSize - 1 do
|
---|
1918 | begin
|
---|
1919 | Tile := RO.Map[Loc1];
|
---|
1920 | if Tile and fModern <> 0 then
|
---|
1921 | begin
|
---|
1922 | Part := (Tile and fModern) shr 25 - 1;
|
---|
1923 | if ColonyShipPlan[Part].nLocResource < maxModern then
|
---|
1924 | begin
|
---|
1925 | ColonyShipPlan[Part].LocResource[ColonyShipPlan[Part].nLocResource] := Loc1;
|
---|
1926 | Inc(ColonyShipPlan[Part].nLocResource);
|
---|
1927 | end;
|
---|
1928 | end;
|
---|
1929 | end;
|
---|
1930 | for Part := 0 to nShipPart - 1 do
|
---|
1931 | if (RO.Ship[Me].Parts[Part] < ShipNeed[Part]) // not enough of this kind already
|
---|
1932 | and (ColonyShipPlan[Part].cixProducing < 0) // no city to produce
|
---|
1933 | and (ColonyShipPlan[Part].nLocResource > 0) then // resource is known
|
---|
1934 | begin
|
---|
1935 | for I := 0 to ColonyShipPlan[Part].nLocResource - 1 do
|
---|
1936 | begin
|
---|
1937 | BestScore := 0;
|
---|
1938 | V21_to_Loc(ColonyShipPlan[Part].LocResource[I], Radius);
|
---|
1939 | for V21 := 1 to 26 do
|
---|
1940 | begin // Check all potential cities in range
|
---|
1941 | CityLoc := Radius[V21];
|
---|
1942 | if CityLoc >= 0 then
|
---|
1943 | begin
|
---|
1944 | Tile := RO.Map[CityLoc];
|
---|
1945 | if (Tile and fTerrain <> fUNKNOWN) and
|
---|
1946 | ((Tile and fTerrain = fForest) or
|
---|
1947 | (Tile and fTerrain = fSwamp) or
|
---|
1948 | (Terrain[Tile and fTerrain].IrrEff > 0)) then
|
---|
1949 | begin
|
---|
1950 | FoodCount := 0;
|
---|
1951 | ProdCount := 0;
|
---|
1952 | ProdExtra := 0;
|
---|
1953 | V21_to_Loc(CityLoc, RadiusC);
|
---|
1954 | for V21C := 1 to 26 do
|
---|
1955 | begin
|
---|
1956 | Loc1 := RadiusC[V21C];
|
---|
1957 | if Loc1 >= 0 then
|
---|
1958 | begin
|
---|
1959 | case RO.Map[Loc1] and (fTerrain or fSpecial) of
|
---|
1960 | fGrass, fGrass + fSpecial1, fSwamp: Inc(FoodCount);
|
---|
1961 | fHills, fHills + fSpecial1: Inc(ProdCount);
|
---|
1962 | fShore + fSpecial1, fDesert + fSpecial1, fPrairie + fSpecial1,
|
---|
1963 | fForest + fSpecial1:
|
---|
1964 | Inc(FoodCount, 2);
|
---|
1965 | fSwamp + fSpecial1, fShore + fSpecial2, fDesert + fSpecial2,
|
---|
1966 | fPrairie + fSpecial2, fTundra + fSpecial2, fArctic + fSpecial1,
|
---|
1967 | fHills + fSpecial2, fMountains + fSpecial1:
|
---|
1968 | begin
|
---|
1969 | Inc(ProdCount);
|
---|
1970 | Inc(ProdExtra);
|
---|
1971 | end;
|
---|
1972 | end;
|
---|
1973 | end;
|
---|
1974 | end;
|
---|
1975 | if FoodCount = 0 then
|
---|
1976 | Score := 0
|
---|
1977 | else
|
---|
1978 | begin
|
---|
1979 | if ProdCount > 7 then
|
---|
1980 | ProdCount := 7;
|
---|
1981 | if FoodCount < 5 then
|
---|
1982 | Dec(ProdCount, 5 - FoodCount);
|
---|
1983 | Score := ProdCount * 4 + ProdExtra * 8 + FoodCount;
|
---|
1984 | Score := Score shl 8 + ((CityLoc xor Me) * 4567) mod 251;
|
---|
1985 | // some unexactness, random but always the same for this tile
|
---|
1986 | end;
|
---|
1987 | if Score > BestScore then
|
---|
1988 | begin
|
---|
1989 | BestScore := Score;
|
---|
1990 | ColonyShipPlan[Part].LocFoundCity[
|
---|
1991 | ColonyShipPlan[Part].nLocFoundCity] :=
|
---|
1992 | CityLoc;
|
---|
1993 | end;
|
---|
1994 | end;
|
---|
1995 | end;
|
---|
1996 | end;
|
---|
1997 | if BestScore > 0 then
|
---|
1998 | Inc(ColonyShipPlan[Part].nLocFoundCity);
|
---|
1999 | end;
|
---|
2000 | end;
|
---|
2001 | end;
|
---|
2002 | end;
|
---|
2003 | end;
|
---|
2004 |
|
---|
2005 | end.
|
---|