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