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