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