source: tags/1.2.0/LocalPlayer/ClientTools.pas

Last change on this file was 205, checked in by chronos, 4 years ago
  • Fixed: Removed various code compilation warnings and hints.
File size: 21.7 KB
Line 
1{$INCLUDE Switches.inc}
2unit ClientTools;
3
4interface
5
6uses
7 Protocol;
8
9const
10 nOfferedResourceWeights = 6;
11 OfferedResourceWeights: array [0 .. nOfferedResourceWeights - 1] of cardinal =
12 (rwOff, rwMaxScience, rwForceScience, rwMaxGrowth, rwForceProd, rwMaxProd);
13
14type
15 TImpOrder = array [0 .. (nImp + 4) div 4 * 4 - 1] of ShortInt;
16 TEnhancementJobs = array [0 .. 11, 0 .. 7] of Byte;
17 JobResultSet = set of 0 .. 39;
18
19var
20 Server: TServerCall;
21 G: TNewGameData;
22 me: integer;
23 MyRO: ^TPlayerContext;
24 MyMap: ^TTileList;
25 MyUn: ^TUnList;
26 MyCity: ^TCityList;
27 MyModel: ^TModelList;
28
29 AdvValue: array [0 .. nAdv - 1] of integer;
30
31function dLoc(Loc, dx, dy: integer): integer;
32function Distance(Loc0, Loc1: integer): integer;
33function UnrestAtLoc(uix, Loc: integer): boolean;
34function GetMoveAdvice(uix, ToLoc: integer;
35 var MoveAdviceData: TMoveAdviceData): integer;
36function ColorOfHealth(Health: integer): integer;
37function IsMultiPlayerGame: boolean;
38procedure ItsMeAgain(p: integer);
39function GetAge(p: integer): integer;
40function IsCivilReportNew(Enemy: integer): boolean;
41function IsMilReportNew(Enemy: integer): boolean;
42function CutCityFoodSurplus(FoodSurplus: integer; IsCityAlive: boolean;
43 gov, size: integer): integer;
44function CityTaxBalance(cix: integer; const CityReport: TCityReportNew)
45 : integer;
46procedure SumCities(var TaxSum, ScienceSum: integer);
47function JobTest(uix, Job: integer; IgnoreResults: JobResultSet = []): boolean;
48procedure GetUnitInfo(Loc: integer; var uix: integer; var UnitInfo: TUnitInfo);
49procedure GetCityInfo(Loc: integer; var cix: integer; var CityInfo: TCityInfo);
50function UnitExhausted(uix: integer): boolean;
51function ModelHash(const ModelInfo: TModelInfo): integer;
52function ProcessEnhancement(uix: integer; const Jobs: TEnhancementJobs)
53 : integer;
54function AutoBuild(cix: integer; const ImpOrder: TImpOrder): boolean;
55procedure DebugMessage(Level: integer; Text: string);
56procedure CityOptimizer_BeginOfTurn;
57procedure CityOptimizer_CityChange(cix: integer);
58procedure CityOptimizer_TileBecomesAvailable(Loc: integer);
59procedure CityOptimizer_ReleaseCityTiles(cix, ReleasedTiles: integer);
60procedure CityOptimizer_BeforeRemoveUnit(uix: integer);
61procedure CityOptimizer_AfterRemoveUnit;
62procedure CityOptimizer_EndOfTurn;
63
64implementation
65
66var
67 CityNeedsOptimize: array [0 .. ncmax - 1] of boolean;
68
69function dLoc(Loc, dx, dy: integer): integer;
70var
71 y0: integer;
72begin
73 y0 := (Loc + G.lx * 1024) div G.lx - 1024;
74 result := (Loc + (dx + y0 and 1 + G.lx * 1024) shr 1) mod G.lx + G.lx
75 * (y0 + dy)
76end;
77
78function Distance(Loc0, Loc1: integer): integer;
79var
80 dx, dy: integer;
81begin
82 inc(Loc0, G.lx * 1024);
83 inc(Loc1, G.lx * 1024);
84 dx := abs(((Loc1 mod G.lx * 2 + Loc1 div G.lx and 1) - (Loc0 mod G.lx * 2 +
85 Loc0 div G.lx and 1) + 3 * G.lx) mod (2 * G.lx) - G.lx);
86 dy := abs(Loc1 div G.lx - Loc0 div G.lx);
87 result := dx + dy + abs(dx - dy) shr 1;
88end;
89
90function UnrestAtLoc(uix, Loc: integer): boolean;
91var
92 uix1: integer;
93begin
94 result := false;
95 if MyModel[MyUn[uix].mix].Flags and mdCivil = 0 then
96 case MyRO.Government of
97 gRepublic, gFuture:
98 result := (MyRO.Territory[Loc] >= 0) and (MyRO.Territory[Loc] <> me) and
99 (MyRO.Treaty[MyRO.Territory[Loc]] < trAlliance);
100 gDemocracy:
101 result := (MyRO.Territory[Loc] < 0) or (MyRO.Territory[Loc] <> me) and
102 (MyRO.Treaty[MyRO.Territory[Loc]] < trAlliance);
103 end;
104 with MyModel[MyUn[uix].mix] do
105 if Cap[mcSeaTrans] + Cap[mcAirTrans] + Cap[mcCarrier] > 0 then
106 for uix1 := 0 to MyRO.nUn - 1 do // check transported units too
107 if (MyUn[uix1].Loc >= 0) and (MyUn[uix1].Master = uix) then
108 result := result or UnrestAtLoc(uix1, Loc);
109end;
110
111function GetMoveAdvice(uix, ToLoc: integer;
112 var MoveAdviceData: TMoveAdviceData): integer;
113var
114 MinEndHealth: integer;
115begin
116 if MyModel[MyUn[uix].mix].Domain = dGround then
117 MinEndHealth := 100
118 else
119 MinEndHealth := 1; // resistent to hostile terrain -- don't consider
120 repeat
121 if MyUn[uix].Health >= MinEndHealth then
122 begin
123 MoveAdviceData.ToLoc := ToLoc;
124 MoveAdviceData.MoreTurns := 999;
125 MoveAdviceData.MaxHostile_MovementLeft := MyUn[uix].Health - MinEndHealth;
126 result := Server(sGetMoveAdvice, me, uix, MoveAdviceData);
127 if (MinEndHealth <= 1) or (result <> eNoWay) then
128 exit;
129 end;
130 case MinEndHealth of
131 100:
132 MinEndHealth := 50;
133 50:
134 MinEndHealth := 25;
135 25:
136 MinEndHealth := 12;
137 else
138 MinEndHealth := 1
139 end;
140 until false end;
141
142 function ColorOfHealth(Health: integer): integer;
143 var
144 red, green: integer;
145 begin
146 green := 400 * Health div 100;
147 if green > 200 then
148 green := 200;
149 red := 510 * (100 - Health) div 100;
150 if red > 255 then
151 red := 255;
152 result := green shl 8 + red
153 end;
154
155 function IsMultiPlayerGame: boolean;
156 var
157 p1: integer;
158 begin
159 result := false;
160 for p1 := 1 to nPl - 1 do
161 if G.RO[p1] <> nil then
162 result := true;
163 end;
164
165 procedure ItsMeAgain(p: integer);
166 begin
167 if G.RO[p] <> nil then
168 MyRO := pointer(G.RO[p])
169 else if G.SuperVisorRO[p] <> nil then
170 MyRO := pointer(G.SuperVisorRO[p])
171 else
172 exit;
173 me := p;
174 MyMap := pointer(MyRO.Map);
175 MyUn := pointer(MyRO.Un);
176 MyCity := pointer(MyRO.City);
177 MyModel := pointer(MyRO.Model);
178 end;
179
180 function GetAge(p: integer): integer;
181 var
182 i: integer;
183 begin
184 if p = me then
185 begin
186 result := 0;
187 for i := 1 to 3 do
188 if MyRO.Tech[AgePreq[i]] >= tsApplicable then
189 result := i;
190 end
191 else
192 begin
193 result := 0;
194 for i := 1 to 3 do
195 if MyRO.EnemyReport[p].Tech[AgePreq[i]] >= tsApplicable then
196 result := i;
197 end
198 end;
199
200 function IsCivilReportNew(Enemy: integer): boolean;
201 var
202 i: integer;
203 begin
204 assert(Enemy <> me);
205 i := MyRO.EnemyReport[Enemy].TurnOfCivilReport;
206 result := (i = MyRO.Turn) or (i = MyRO.Turn - 1) and (Enemy > me);
207 end;
208
209 function IsMilReportNew(Enemy: integer): boolean;
210 var
211 i: integer;
212 begin
213 assert(Enemy <> me);
214 i := MyRO.EnemyReport[Enemy].TurnOfMilReport;
215 result := (i = MyRO.Turn) or (i = MyRO.Turn - 1) and (Enemy > me);
216 end;
217
218 function CutCityFoodSurplus(FoodSurplus: integer; IsCityAlive: boolean;
219 gov, size: integer): integer;
220 begin
221 result := FoodSurplus;
222 if not IsCityAlive or (result > 0) and
223 ((gov = gFuture) or (size >= NeedAqueductSize) and (result < 2)) then
224 result := 0; { no growth }
225 end;
226
227 function CityTaxBalance(cix: integer;
228 const CityReport: TCityReportNew): integer;
229 var
230 i: integer;
231 begin
232 result := 0;
233 if (CityReport.HappinessBalance >= 0) { no disorder }
234 and (MyCity[cix].Flags and chCaptured = 0) then // not captured
235 begin
236 inc(result, CityReport.Tax);
237 if (MyCity[cix].Project and (cpImp + cpIndex) = cpImp + imTrGoods) and
238 (CityReport.Production > 0) then
239 inc(result, CityReport.Production);
240 if ((MyRO.Government = gFuture) or (MyCity[cix].size >= NeedAqueductSize)
241 and (CityReport.FoodSurplus < 2)) and (CityReport.FoodSurplus > 0) then
242 inc(result, CityReport.FoodSurplus);
243 end;
244 for i := 28 to nImp - 1 do
245 if MyCity[cix].Built[i] > 0 then
246 dec(result, Imp[i].Maint);
247 end;
248
249 procedure SumCities(var TaxSum, ScienceSum: integer);
250 var
251 cix: integer;
252 CityReport: TCityReportNew;
253 begin
254 TaxSum := MyRO.OracleIncome;
255 ScienceSum := 0;
256 if MyRO.Government = gAnarchy then
257 exit;
258 for cix := 0 to MyRO.nCity - 1 do
259 if MyCity[cix].Loc >= 0 then
260 begin
261 CityReport.HypoTiles := -1;
262 CityReport.HypoTaxRate := -1;
263 CityReport.HypoLuxuryRate := -1;
264 Server(sGetCityReportNew, me, cix, CityReport);
265 if (CityReport.HappinessBalance >= 0) { no disorder }
266 and (MyCity[cix].Flags and chCaptured = 0) then // not captured
267 ScienceSum := ScienceSum + CityReport.Science;
268 TaxSum := TaxSum + CityTaxBalance(cix, CityReport);
269 end;
270 end;
271
272 function JobTest(uix, Job: integer; IgnoreResults: JobResultSet): boolean;
273 var
274 Test: integer;
275 begin
276 Test := Server(sStartJob + Job shl 4 - sExecute, me, uix, nil^);
277 result := (Test >= rExecuted) or (Test in IgnoreResults);
278 end;
279
280 procedure GetUnitInfo(Loc: integer; var uix: integer;
281 var UnitInfo: TUnitInfo);
282 var
283 i, Cnt: integer;
284 begin
285 if MyMap[Loc] and fOwned <> 0 then
286 begin
287 Server(sGetDefender, me, Loc, uix);
288 Cnt := 0;
289 for i := 0 to MyRO.nUn - 1 do
290 if MyUn[i].Loc = Loc then
291 inc(Cnt);
292 MakeUnitInfo(me, MyUn[uix], UnitInfo);
293 if Cnt > 1 then
294 UnitInfo.Flags := UnitInfo.Flags or unMulti;
295 end
296 else
297 begin
298 uix := MyRO.nEnemyUn - 1;
299 while (uix >= 0) and (MyRO.EnemyUn[uix].Loc <> Loc) do
300 dec(uix);
301 UnitInfo := MyRO.EnemyUn[uix];
302 end
303 end; { GetUnitInfo }
304
305 procedure GetCityInfo(Loc: integer; var cix: integer;
306 var CityInfo: TCityInfo);
307 begin
308 if MyMap[Loc] and fOwned <> 0 then
309 begin
310 CityInfo.Loc := Loc;
311 cix := MyRO.nCity - 1;
312 while (cix >= 0) and (MyCity[cix].Loc <> Loc) do
313 dec(cix);
314 with CityInfo do
315 begin
316 Owner := me;
317 ID := MyCity[cix].ID;
318 size := MyCity[cix].size;
319 Flags := 0;
320 if MyCity[cix].Built[imPalace] > 0 then
321 inc(Flags, ciCapital);
322 if (MyCity[cix].Built[imWalls] > 0) or
323 (MyMap[MyCity[cix].Loc] and fGrWall <> 0) then
324 inc(Flags, ciWalled);
325 if MyCity[cix].Built[imCoastalFort] > 0 then
326 inc(Flags, ciCoastalFort);
327 if MyCity[cix].Built[imMissileBat] > 0 then
328 inc(Flags, ciMissileBat);
329 if MyCity[cix].Built[imBunker] > 0 then
330 inc(Flags, ciBunker);
331 if MyCity[cix].Built[imSpacePort] > 0 then
332 inc(Flags, ciSpacePort);
333 end
334 end
335 else
336 begin
337 cix := MyRO.nEnemyCity - 1;
338 while (cix >= 0) and (MyRO.EnemyCity[cix].Loc <> Loc) do
339 dec(cix);
340 CityInfo := MyRO.EnemyCity[cix];
341 end
342 end;
343
344 function UnitExhausted(uix: integer): boolean;
345 // check if another move of this unit is still possible
346 var
347 dx, dy: integer;
348 begin
349 result := true;
350 if (MyUn[uix].Movement > 0) or
351 (MyRO.Wonder[woShinkansen].EffectiveOwner = me) then
352 if (MyUn[uix].Movement >= 100) or
353 ((MyModel[MyUn[uix].mix].Kind = mkCaravan) and
354 (MyMap[MyUn[uix].Loc] and fCity <> 0)) then
355 result := false
356 else
357 for dx := -2 to 2 do
358 for dy := -2 to 2 do
359 if abs(dx) + abs(dy) = 2 then
360 if Server(sMoveUnit - sExecute + dx and 7 shl 4 + dy and 7 shl 7,
361 me, uix, nil^) >= rExecuted then
362 result := false;
363 end;
364
365 function ModelHash(const ModelInfo: TModelInfo): integer;
366 var
367 i, FeatureCode, Hash1, Hash2, Hash2r, d: cardinal;
368 begin
369 with ModelInfo do
370 if Kind > mkEnemyDeveloped then
371 result := integer($C0000000 + Speed div 50 + Kind shl 8)
372 else
373 begin
374 FeatureCode := 0;
375 for i := mcFirstNonCap to nFeature - 1 do
376 if 1 shl Domain and Feature[i].Domains <> 0 then
377 begin
378 FeatureCode := FeatureCode * 2;
379 if 1 shl (i - mcFirstNonCap) <> 0 then
380 inc(FeatureCode);
381 end;
382 case Domain of
383 dGround:
384 begin
385 assert(FeatureCode < 1 shl 8);
386 assert(Attack < 5113);
387 assert(Defense < 2273);
388 assert(Cost < 1611);
389 Hash1 := (Attack * 2273 + Defense) * 9 + (Speed - 150) div 50;
390 Hash2 := FeatureCode * 1611 + Cost;
391 end;
392 dSea:
393 begin
394 assert(FeatureCode < 1 shl 9);
395 assert(Attack < 12193);
396 assert(Defense < 6097);
397 assert(Cost < 4381);
398 Hash1 := ((Attack * 6097 + Defense) * 5 + (Speed - 350)
399 div 100) * 2;
400 if Weight >= 6 then
401 inc(Hash1);
402 Hash2 := ((TTrans * 17 + ATrans_Fuel) shl 9 + FeatureCode) *
403 4381 + Cost;
404 end;
405 dAir:
406 begin
407 assert(FeatureCode < 1 shl 5);
408 assert(Attack < 2407);
409 assert(Defense < 1605);
410 assert(Bombs < 4813);
411 assert(Cost < 2089);
412 Hash1 := (Attack * 1605 + Defense) shl 5 + FeatureCode;
413 Hash2 := ((Bombs * 7 + ATrans_Fuel) * 4 + TTrans) * 2089 + Cost;
414 end;
415 end;
416 Hash2r := 0;
417 for i := 0 to 7 do
418 begin
419 Hash2r := Hash2r * 13;
420 d := Hash2 div 13;
421 inc(Hash2r, Hash2 - d * 13);
422 Hash2 := d
423 end;
424 result := integer(Domain shl 30 + Hash1 xor Hash2r)
425 end
426 end;
427
428 function ProcessEnhancement(uix: integer;
429 const Jobs: TEnhancementJobs): integer;
430 { return values:
431 eJobDone - all applicable jobs done
432 eOK - enhancement not complete
433 eDied - job done and died (thurst) }
434 var
435 stage, NextJob, Tile: integer;
436 Done: Set of jNone .. jPoll;
437 begin
438 Done := [];
439 Tile := MyMap[MyUn[uix].Loc];
440 if Tile and fRoad <> 0 then
441 include(Done, jRoad);
442 if Tile and fRR <> 0 then
443 include(Done, jRR);
444 if (Tile and fTerImp = tiIrrigation) or (Tile and fTerImp = tiFarm) then
445 include(Done, jIrr);
446 if Tile and fTerImp = tiFarm then
447 include(Done, jFarm);
448 if Tile and fTerImp = tiMine then
449 include(Done, jMine);
450 if Tile and fPoll = 0 then
451 include(Done, jPoll);
452
453 if MyUn[uix].Job = jNone then
454 result := eJobDone
455 else
456 result := eOK;
457 while (result <> eOK) and (result <> eDied) do
458 begin
459 stage := -1;
460 repeat
461 if stage = -1 then
462 NextJob := jPoll
463 else
464 NextJob := Jobs[Tile and fTerrain, stage];
465 if (NextJob = jNone) or not(NextJob in Done) then
466 Break;
467 inc(stage);
468 until stage = 5;
469 if (stage = 5) or (NextJob = jNone) then
470 begin
471 result := eJobDone;
472 Break;
473 end; // tile enhancement complete
474 result := Server(sStartJob + NextJob shl 4, me, uix, nil^);
475 include(Done, NextJob)
476 end;
477 end;
478
479 function AutoBuild(cix: integer; const ImpOrder: TImpOrder): boolean;
480 var
481 i, NewProject: integer;
482 begin
483 result := false;
484 if (MyCity[cix].Project and (cpImp + cpIndex) = cpImp + imTrGoods) or
485 (MyCity[cix].Flags and chProduction <> 0) then
486 begin
487 i := 0;
488 repeat
489 while (ImpOrder[i] >= 0) and (MyCity[cix].Built[ImpOrder[i]] > 0) do
490 inc(i);
491 if ImpOrder[i] < 0 then
492 Break;
493 assert(i < nImp);
494 NewProject := cpImp + ImpOrder[i];
495 if Server(sSetCityProject, me, cix, NewProject) >= rExecuted then
496 begin
497 result := true;
498 CityOptimizer_CityChange(cix);
499 Break;
500 end;
501 inc(i);
502 until false end end;
503
504 procedure CalculateAdvValues;
505 var
506 i, j: integer;
507 known: array [0 .. nAdv - 1] of integer;
508
509 procedure MarkPreqs(i: integer);
510 begin
511 if known[i] = 0 then
512 begin
513 known[i] := 1;
514 if (i <> adScience) and (i <> adMassProduction) then
515 begin
516 if (AdvPreq[i, 0] >= 0) then
517 MarkPreqs(AdvPreq[i, 0]);
518 if (AdvPreq[i, 1] >= 0) then
519 MarkPreqs(AdvPreq[i, 1]);
520 end
521 end
522 end;
523
524 begin
525 FillChar(AdvValue, SizeOf(AdvValue), 0);
526 for i := 0 to nAdv - 1 do
527 begin
528 FillChar(known, SizeOf(known), 0);
529 MarkPreqs(i);
530 for j := 0 to nAdv - 1 do
531 if known[j] > 0 then
532 inc(AdvValue[i]);
533 if i in FutureTech then
534 inc(AdvValue[i], 3000)
535 else if known[adMassProduction] > 0 then
536 inc(AdvValue[i], 2000)
537 else if known[adScience] > 0 then
538 inc(AdvValue[i], 1000)
539 end;
540 end;
541
542 procedure DebugMessage(Level: integer; Text: string);
543 begin
544 Server(sMessage, me, Level, pchar(Text)^)
545 end;
546
547 function MarkCitiesAround(Loc, cixExcept: integer): boolean;
548 // return whether a city was marked
549 var
550 cix: integer;
551 begin
552 result := false;
553 for cix := 0 to MyRO.nCity - 1 do
554 if (cix <> cixExcept) and (MyCity[cix].Loc >= 0) and
555 (MyCity[cix].Flags and chCaptured = 0) and
556 (Distance(MyCity[cix].Loc, Loc) <= 5) then
557 begin
558 CityNeedsOptimize[cix] := true;
559 result := true;
560 end
561 end;
562
563 procedure OptimizeCities(CheckOnly: boolean);
564 var
565 cix, fix, dx, dy, Loc1, OptiType: integer;
566 Done: boolean;
567 Advice: TCityTileAdviceData;
568 begin
569 repeat
570 Done := true;
571 for cix := 0 to MyRO.nCity - 1 do
572 if CityNeedsOptimize[cix] then begin
573 OptiType := (MyCity[cix].Status shr 4) and $0F;
574 if OptiType <> 0 then begin
575 Advice.ResourceWeights := OfferedResourceWeights[OptiType];
576 Server(sGetCityTileAdvice, me, cix, Advice);
577 if Advice.Tiles <> MyCity[cix].Tiles then
578 if CheckOnly then begin
579 // TODO: What is this assert for?
580 // Need to optimize city tiles but CheckOnly true?
581 //assert(false)
582 end else begin
583 for fix := 1 to 26 do
584 if MyCity[cix].Tiles and not Advice.Tiles and
585 (1 shl fix) <> 0 then
586 begin // tile no longer used by this city -- check using it by another
587 dy := fix shr 2 - 3;
588 dx := fix and 3 shl 1 - 3 + (dy + 3) and 1;
589 Loc1 := dLoc(MyCity[cix].Loc, dx, dy);
590 if MarkCitiesAround(Loc1, cix) then
591 Done := false;
592 end;
593 Server(sSetCityTiles, me, cix, Advice.Tiles);
594 end;
595 end;
596 CityNeedsOptimize[cix] := false;
597 end;
598 until Done;
599 end;
600
601 procedure CityOptimizer_BeginOfTurn;
602 var
603 cix: integer;
604 begin
605 FillChar(CityNeedsOptimize, MyRO.nCity - 1, 0); // false
606 if MyRO.Government <> gAnarchy then
607 begin
608 for cix := 0 to MyRO.nCity - 1 do
609 if (MyCity[cix].Loc >= 0) and (MyCity[cix].Flags and chCaptured = 0)
610 then
611 CityNeedsOptimize[cix] := true;
612 OptimizeCities(false); // optimize all cities
613 end
614 end;
615
616 procedure CityOptimizer_CityChange(cix: integer);
617 begin
618 if (MyRO.Government <> gAnarchy) and
619 (MyCity[cix].Flags and chCaptured = 0) then
620 begin
621 CityNeedsOptimize[cix] := true;
622 OptimizeCities(false);
623 end
624 end;
625
626 procedure CityOptimizer_TileBecomesAvailable(Loc: integer);
627 begin
628 if (MyRO.Government <> gAnarchy) and MarkCitiesAround(Loc, -1) then
629 OptimizeCities(false);
630 end;
631
632 procedure CityOptimizer_ReleaseCityTiles(cix, ReleasedTiles: integer);
633 var
634 fix, dx, dy, Loc1: integer;
635 Done: boolean;
636 begin
637 if (MyRO.Government <> gAnarchy) and (ReleasedTiles <> 0) then
638 begin
639 Done := true;
640 for fix := 1 to 26 do
641 if ReleasedTiles and (1 shl fix) <> 0 then
642 begin
643 dy := fix shr 2 - 3;
644 dx := fix and 3 shl 1 - 3 + (dy + 3) and 1;
645 Loc1 := dLoc(MyCity[cix].Loc, dx, dy);
646 if MarkCitiesAround(Loc1, cix) then
647 Done := false;
648 end;
649 if not Done then
650 OptimizeCities(false);
651 end
652 end;
653
654 procedure CityOptimizer_BeforeRemoveUnit(uix: integer);
655 var
656 uix1: integer;
657 begin
658 if MyRO.Government <> gAnarchy then
659 begin
660 if MyUn[uix].Home >= 0 then
661 CityNeedsOptimize[MyUn[uix].Home] := true;
662
663 // transported units are also removed
664 for uix1 := 0 to MyRO.nUn - 1 do
665 if (MyUn[uix1].Loc >= 0) and (MyUn[uix1].Master = uix) and
666 (MyUn[uix1].Home >= 0) then
667 CityNeedsOptimize[MyUn[uix1].Home] := true;
668 end
669 end;
670
671 procedure CityOptimizer_AfterRemoveUnit;
672 begin
673 if MyRO.Government <> gAnarchy then
674 OptimizeCities(false);
675 end;
676
677 procedure CityOptimizer_EndOfTurn;
678 // all cities should already be optimized here -- only check this
679 var
680 cix: integer;
681 begin
682{$IFOPT O-}
683 if MyRO.Government <> gAnarchy then
684 begin
685 FillChar(CityNeedsOptimize, MyRO.nCity - 1, 0); // false
686 for cix := 0 to MyRO.nCity - 1 do
687 if (MyCity[cix].Loc >= 0) and (MyCity[cix].Flags and chCaptured = 0)
688 then
689 CityNeedsOptimize[cix] := true;
690 OptimizeCities(true); // check all cities
691 end;
692{$ENDIF}
693 end;
694
695initialization
696
697Assert(nImp < 128);
698CalculateAdvValues;
699
700end.
Note: See TracBrowser for help on using the repository browser.