Ignore:
Timestamp:
Mar 9, 2021, 9:19:49 AM (3 years ago)
Author:
chronos
Message:
  • Modified: Synced code with current trunk version.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/highdpi/AI/StdAI/AI.pas

    r210 r303  
    66
    77uses
    8 {$IFDEF DEBUG}SysUtils,Names,{$ENDIF} // necessary for debug exceptions
    9 {$IFDEF PERF}SysUtils,Windows,{$ENDIF} // necessary for performance measurement
    10 Protocol, CustomAI, ToolAI, Barbarina;
    11 
     8{$IFDEF DEBUG}SysUtils, Names,{$ENDIF} // necessary for debug exceptions
     9{$IFDEF PERF}SysUtils, Windows,{$ENDIF} // necessary for performance measurement
     10  Protocol, CustomAI, ToolAI, Barbarina;
    1211
    1312const
    14 WaitAfterReject=20; // don't try to contact this number of turn after contact was rejected
    15 MinCityFood=3;
    16 LeaveDespotism=80; // stay in despotism until this turn
    17 TechReportOutdated=30;
    18 MilProdShare=50; // minimum share of total production to specialize in military production
    19 
    20 FutureTech=[futResearchTechnology,futProductionTechnology,futArmorTechnology,
    21   futMissileTechnology];
    22 
    23 nResearchOrder=46;
    24 ResearchOrder: array[0..1,0..nResearchOrder-1] of integer=
    25 ((adWheel,adWarriorCode,adHorsebackRiding,adCeremonialBurial,adPolytheism,
    26 adMonarchy,adMysticism,adPoetry,adAstronomy,adMonotheism,
    27 adTheology,adChivalry,adPottery,adMedicine,adGunpowder,adChemistry,
    28 adExplosives,adUniversity,adTactics,adSeafaring,adNavigation,adRefining,adCombustionEngine,
    29 adAutomobile,adPhysics,adMagnetism,adElectricity,adRefrigeration,
    30 adRadioCommunication,adTheoryOfGravity,adAtomicTheory,adElectronics,
    31 adMassProduction,adPlastics,adFlight,adEnvironmentalism,
    32 adSanitation,adMin,adComputers,adRecycling,adSyntheticFood,
    33 adSelfContainedEnvironment,adNuclearFission,adNuclearPower,adTheLaser,
    34 adIntelligenArms),
    35 (adWheel,adWarriorCode,adHorsebackRiding,adAlphabet,adMapMaking,adBronzeWorking,adWriting,
    36 adCodeOfLaws,adCurrency,adTrade,adLiterature,adTheRepublic,adMathematics,
    37 adPhilosophy,adScience,adMasonry,adConstruction,adEngineering,adInvention,
    38 adIronWorking,adBridgeBuilding,adSteamEngine,adRailroad,adSteel,
    39 adBanking,adIndustrialization,adConscription,adDemocracy,adEconomics,
    40 adTheCorporation,adMassProduction,adRobotics,adCommunism,adMetallurgy,
    41 adBallistics,adMobileWarfare,adAmphibiousWarfare,adMin,adComputers,adRocketry,adAdvancedRocketry,
    42 adAdvancedFlight,adSpaceFlight,adComposites,adIntelligence,adCombinedArms));
    43 
    44 LeaveOutTechs=[adPolytheism,adMysticism,adInvention,adEconomics,adPottery,
    45 adMedicine,adEnvironmentalism,adRefining,adTrade,adLiterature,adMathematics,
    46 adPhilosophy,adChemistry,adConscription,adCombustionEngine,adPhysics,
    47 adTheoryOfGravity,adAtomicTheory,adSyntheticFood,adNuclearFission];
    48 
    49 TechValue_ForResearch_LeaveOut=$700;
    50 TechValue_ForResearch_Urgent=$600;
    51 TechValue_ForResearch_Next=$400;
    52 TechValue_ForResearch=$FF;
    53 ForceNeeded_NoLeaveOut=20; // advancedness behind to state-of-art
    54 ForceNeeded_LeaveOut=30; // advancedness behind of state-of-art
    55 Compromise=6;
    56 
    57 // basic strategies
    58 bGender=$0001;
    59 bMale=$0000;
    60 bFemale=$0001;
    61 bBarbarina=$0006;
    62 bBarbarina_Hide=$0002;
    63 
    64 // model categories
    65 nModelCat=4;
    66 mctNone=-1; mctGroundDefender=0; mctGroundAttacker=1; mctTransport=2; mctCruiser=3;
    67 
    68 // mil research
    69 BetterQuality: array[0..nModelCat-1] of integer=(50,50,80,80);
    70 MaxBuildWorseThanBestModel=20; MaxExistWorseThanBestModel=50;
    71 
    72 maxCOD=256;
    73 PresenceUnknown=$10000;
    74 
    75 nRequestedTechs=48;
    76 
    77 PlayerHash: array[0..nPl-1] of integer=(7,6,0,2,10,8,12,14,4,1,3,5,9,11,13);
     13  WaitAfterReject = 20;
     14  // don't try to contact this number of turn after contact was rejected
     15  MinCityFood = 3;
     16  LeaveDespotism = 80; // stay in despotism until this turn
     17  TechReportOutdated = 30;
     18  MilProdShare = 50;
     19  // minimum share of total production to specialize in military production
     20
     21  FutureTech = [futResearchTechnology, futProductionTechnology,
     22    futArmorTechnology, futMissileTechnology];
     23
     24  nResearchOrder = 46;
     25  ResearchOrder: array[0..1, 0..nResearchOrder - 1] of integer =
     26    ((adWheel, adWarriorCode, adHorsebackRiding, adCeremonialBurial, adPolytheism,
     27    adMonarchy, adMysticism, adPoetry, adAstronomy, adMonotheism,
     28    adTheology, adChivalry, adPottery, adMedicine, adGunpowder, adChemistry,
     29    adExplosives, adUniversity, adTactics, adSeafaring, adNavigation, adRefining,
     30    adCombustionEngine,
     31    adAutomobile, adPhysics, adMagnetism, adElectricity, adRefrigeration,
     32    adRadioCommunication, adTheoryOfGravity, adAtomicTheory, adElectronics,
     33    adMassProduction, adPlastics, adFlight, adEnvironmentalism,
     34    adSanitation, adMin, adComputers, adRecycling, adSyntheticFood,
     35    adSelfContainedEnvironment, adNuclearFission, adNuclearPower, adTheLaser,
     36    adIntelligenArms),
     37    (adWheel, adWarriorCode, adHorsebackRiding, adAlphabet, adMapMaking,
     38    adBronzeWorking, adWriting,
     39    adCodeOfLaws, adCurrency, adTrade, adLiterature, adTheRepublic, adMathematics,
     40    adPhilosophy, adScience, adMasonry, adConstruction, adEngineering, adInvention,
     41    adIronWorking, adBridgeBuilding, adSteamEngine, adRailroad, adSteel,
     42    adBanking, adIndustrialization, adConscription, adDemocracy, adEconomics,
     43    adTheCorporation, adMassProduction, adRobotics, adCommunism, adMetallurgy,
     44    adBallistics, adMobileWarfare, adAmphibiousWarfare, adMin, adComputers,
     45    adRocketry, adAdvancedRocketry,
     46    adAdvancedFlight, adSpaceFlight, adComposites, adIntelligence, adCombinedArms));
     47
     48  LeaveOutTechs = [adPolytheism, adMysticism, adInvention, adEconomics,
     49    adPottery, adMedicine, adEnvironmentalism, adRefining, adTrade,
     50    adLiterature, adMathematics, adPhilosophy, adChemistry, adConscription,
     51    adCombustionEngine, adPhysics, adTheoryOfGravity, adAtomicTheory,
     52    adSyntheticFood, adNuclearFission];
     53
     54  TechValue_ForResearch_LeaveOut = $700;
     55  TechValue_ForResearch_Urgent = $600;
     56  TechValue_ForResearch_Next = $400;
     57  TechValue_ForResearch = $FF;
     58  ForceNeeded_NoLeaveOut = 20; // advancedness behind to state-of-art
     59  ForceNeeded_LeaveOut = 30; // advancedness behind of state-of-art
     60  Compromise = 6;
     61
     62  // basic strategies
     63  bGender = $0001;
     64  bMale = $0000;
     65  bFemale = $0001;
     66  bBarbarina = $0006;
     67  bBarbarina_Hide = $0002;
     68
     69  // model categories
     70  nModelCat = 4;
     71  mctNone = -1;
     72  mctGroundDefender = 0;
     73  mctGroundAttacker = 1;
     74  mctTransport = 2;
     75  mctCruiser = 3;
     76
     77  // mil research
     78  BetterQuality: array[0..nModelCat - 1] of integer = (50, 50, 80, 80);
     79  MaxBuildWorseThanBestModel = 20;
     80  MaxExistWorseThanBestModel = 50;
     81
     82  maxCOD = 256;
     83  PresenceUnknown = $10000;
     84
     85  nRequestedTechs = 48;
     86
     87  PlayerHash: array[0..nPl - 1] of integer =
     88    (7, 6, 0, 2, 10, 8, 12, 14, 4, 1, 3, 5, 9, 11, 13);
    7889
    7990type
    80 Suggestion=(suContact, suPeace, suFriendly);
    81 
    82 TPersistentData=record
    83   LastResearchTech, BehaviorFlags, TheologyPartner: integer;
    84   RejectTurn: array[Suggestion,0..15] of smallint;
    85   RequestedTechs: array[0..nRequestedTechs-1] of integer;
     91  Suggestion = (suContact, suPeace, suFriendly);
     92
     93  TPersistentData = record
     94    LastResearchTech, BehaviorFlags, TheologyPartner: integer;
     95    RejectTurn: array[Suggestion, 0..15] of smallint;
     96    RequestedTechs: array[0..nRequestedTechs - 1] of integer;
    8697    // ad + p shl 8 + Turn shl 16
    8798  end;
    8899
    89 TAI = class(TBarbarina)
    90   constructor Create(Nation: integer); override;
    91 
    92   procedure SetDataDefaults; override;
    93 
    94 protected
    95   Data: ^TPersistentData;
    96   WarNations, BombardingNations, mixSettlers, mixCaravan, mixTownGuard,
     100  TAI = class(TBarbarina)
     101    constructor Create(Nation: integer); override;
     102
     103    procedure SetDataDefaults; override;
     104
     105  protected
     106    Data: ^TPersistentData;
     107    WarNations, BombardingNations, mixSettlers, mixCaravan, mixTownGuard,
    97108    mixSlaves, mixMilitia, mixCruiser, OceanWithShip: integer;
    98   NegoCause: (Routine,CheckBarbarina);
    99   SettlerSurplus: array[0..maxCOD-1] of integer;
    100   uixPatrol: array[0..maxCOD-1] of integer;
    101 
    102   ContinentPresence: array[0..maxCOD-1] of integer;
    103   OceanPresence: array[0..maxCOD-1] of integer;
    104   UnitLack: array[0..maxCOD-1,mctGroundDefender..mctGroundAttacker] of integer;
    105 
    106   TotalPopulation: array[0..nPl-1] of integer;
    107   ContinentPopulation: array[0..nPl-1,0..maxCOD-1] of integer;
     109    NegoCause: (Routine, CheckBarbarina);
     110    SettlerSurplus: array[0..maxCOD - 1] of integer;
     111    uixPatrol: array[0..maxCOD - 1] of integer;
     112
     113    ContinentPresence: array[0..maxCOD - 1] of integer;
     114    OceanPresence: array[0..maxCOD - 1] of integer;
     115    UnitLack: array[0..maxCOD - 1, mctGroundDefender..mctGroundAttacker] of integer;
     116
     117    TotalPopulation: array[0..nPl - 1] of integer;
     118    ContinentPopulation: array[0..nPl - 1, 0..maxCOD - 1] of integer;
    108119    // 1 means enemy territory spotted but no city
    109   DistrictPopulation: array[0..maxCOD-1] of integer;
    110 
    111   ModelCat: array[0..nMmax-1] of integer;
    112   ModelQuality: array[0..nMmax-1] of integer;
    113   ModelBestQuality: array[0..nModelCat-1] of integer;
    114 
    115   AdvanceValue: array[0..nAdv-1] of integer;
    116   AdvanceValuesSet: boolean;
    117 
    118   procedure DoTurn; override;
    119   procedure DoNegotiation; override;
    120   function ChooseResearchAdvance: integer; override;
    121   function ChooseStealAdvance: integer; override;
    122   function ChooseGovernment: integer; override;
    123   function WantNegotiation(Nation: integer; NegoTime: TNegoTime): boolean; override;
    124   function OnNegoRejected_CancelTreaty: boolean; override;
    125 
    126   procedure FindBestTrade(Nation: integer; var adWanted, adGiveAway: integer);
    127   procedure CheckGender;
    128   procedure AnalyzeMap;
    129   procedure CollectModelCatStat;
    130   procedure AttackAndPatrol;
    131   procedure MoveUnitsHome;
    132   procedure CheckAttack(uix: integer);
    133   procedure Patrol(uix: integer);
    134   procedure SetCityProduction;
    135   procedure SetAdvanceValues;
    136   function HavePort: boolean;
     120    DistrictPopulation: array[0..maxCOD - 1] of integer;
     121
     122    ModelCat: array[0..nMmax - 1] of integer;
     123    ModelQuality: array[0..nMmax - 1] of integer;
     124    ModelBestQuality: array[0..nModelCat - 1] of integer;
     125
     126    AdvanceValue: array[0..nAdv - 1] of integer;
     127    AdvanceValuesSet: boolean;
     128
     129    procedure DoTurn; override;
     130    procedure DoNegotiation; override;
     131    function ChooseResearchAdvance: integer; override;
     132    function ChooseStealAdvance: integer; override;
     133    function ChooseGovernment: integer; override;
     134    function WantNegotiation(Nation: integer; NegoTime: TNegoTime): boolean; override;
     135    function OnNegoRejected_CancelTreaty: boolean; override;
     136
     137    procedure FindBestTrade(Nation: integer; var adWanted, adGiveAway: integer);
     138    procedure CheckGender;
     139    procedure AnalyzeMap;
     140    procedure CollectModelCatStat;
     141    procedure AttackAndPatrol;
     142    procedure MoveUnitsHome;
     143    procedure CheckAttack(uix: integer);
     144    procedure Patrol(uix: integer);
     145    procedure SetCityProduction;
     146    procedure SetAdvanceValues;
     147    function HavePort: boolean;
    137148  {$IFDEF DEBUG}procedure TraceAdvanceValues(Nation: integer);{$ENDIF}
    138149
    139   // research
    140   procedure RateModel(const mi: TModelInfo; var Category, Quality: integer);
    141   procedure RateMyModel(mix: integer; var Category, Quality: integer);
    142   function IsBetterModel(const mi: TModelInfo): boolean;
    143 
    144   //terraforming
    145   procedure TileWorkPlan(Loc, cix: integer;
    146     var Value, NextJob, TotalWork: integer);
    147   procedure ProcessSettlers;
    148 
    149   // diplomacy
    150   function MostWanted(Nation, adGiveAway: integer): integer;
     150    // research
     151    procedure RateModel(const mi: TModelInfo; var Category, Quality: integer);
     152    procedure RateMyModel(mix: integer; var Category, Quality: integer);
     153    function IsBetterModel(const mi: TModelInfo): boolean;
     154
     155    //terraforming
     156    procedure TileWorkPlan(Loc, cix: integer; var Value, NextJob, TotalWork: integer);
     157    procedure ProcessSettlers;
     158
     159    // diplomacy
     160    function MostWanted(Nation, adGiveAway: integer): integer;
    151161
    152162  end;
     
    156166
    157167uses
    158 Pile;
     168  Pile;
    159169
    160170const
    161 // fine adjustment
    162 Aggressive=40; // 0 = never attacks, 100 = attacks even with heavy losses
    163 DestroyBonus=30; // percent of building cost
     171  // fine adjustment
     172  Aggressive = 40; // 0 = never attacks, 100 = attacks even with heavy losses
     173  DestroyBonus = 30; // percent of building cost
    164174
    165175var
    166 LeaveOutValue: array[0..nAdv-1] of integer;
     176  LeaveOutValue: array[0..nAdv - 1] of integer;
    167177
    168178
    169179constructor TAI.Create(Nation: integer);
    170180begin
    171 inherited;
    172 Data:=pointer(RO.Data);
    173 {$IFDEF DEBUG}if Nation=1 then SetDebugMap(DebugMap);{$ENDIF}
    174 AdvanceValuesSet:=false;
     181  inherited;
     182  Data := pointer(RO.Data);
     183{$IFDEF DEBUG}
     184  if Nation = 1 then
     185    SetDebugMap(DebugMap);
     186{$ENDIF}
     187  AdvanceValuesSet := False;
    175188end;
    176189
    177190procedure TAI.SetDataDefaults;
    178191begin
    179 with Data^ do
    180   begin
    181   LastResearchTech:=-1;
    182   if PlayerHash[me]>7 then BehaviorFlags:=bFemale else BehaviorFlags:=bMale;
    183   DebugMessage(1, 'Gender:='+char(48+BehaviorFlags and bGender));
    184   TheologyPartner:=-1;
    185   fillchar(RejectTurn,sizeof(RejectTurn),$FF);
    186   Fillchar(RequestedTechs, sizeof(RequestedTechs), $FF);
    187   end
     192  with Data^ do
     193  begin
     194    LastResearchTech := -1;
     195    if PlayerHash[me] > 7 then
     196      BehaviorFlags := bFemale
     197    else
     198      BehaviorFlags := bMale;
     199    DebugMessage(1, 'Gender:=' + char(48 + BehaviorFlags and bGender));
     200    TheologyPartner := -1;
     201    fillchar(RejectTurn, sizeof(RejectTurn), $FF);
     202    Fillchar(RequestedTechs, sizeof(RequestedTechs), $FF);
     203  end;
    188204end;
    189205
    190206function TAI.OnNegoRejected_CancelTreaty: boolean;
    191207begin
    192 Data.RejectTurn[suContact,Opponent]:=RO.Turn;
    193 result:= Data.BehaviorFlags and bBarbarina<>0;
     208  Data.RejectTurn[suContact, Opponent] := RO.Turn;
     209  Result := Data.BehaviorFlags and bBarbarina <> 0;
    194210end;
    195211
     
    201217procedure TAI.RateModel(const mi: TModelInfo; var Category, Quality: integer);
    202218var
    203 EffectiveTransport: integer;
     219  EffectiveTransport: integer;
    204220begin
    205 if mi.Kind>=mkScout then
    206   begin Category:=mctNone; exit end;
    207 case mi.Domain of
    208   dGround:
    209     if mi.Speed>=250 then
    210       begin
    211       Category:=mctGroundAttacker;
    212       if mi.Attack=0 then Quality:=0
     221  if mi.Kind >= mkScout then
     222  begin
     223    Category := mctNone;
     224    exit;
     225  end;
     226  case mi.Domain of
     227    dGround:
     228      if mi.Speed >= 250 then
     229      begin
     230        Category := mctGroundAttacker;
     231        if mi.Attack = 0 then
     232          Quality := 0
     233        else
     234        begin
     235          Quality := trunc(100 * (ln(mi.Attack) + ln(mi.Defense) +
     236            ln(mi.Speed / 150) * 1.7 - ln(mi.Cost)));
     237          if mi.Cap and (1 shl (mcFanatic - mcFirstNonCap)) <> 0 then
     238            Inc(Quality, trunc(100 * ln(1.5)));
     239          if mi.Cap and (1 shl (mcLongRange - mcFirstNonCap)) <> 0 then
     240            Inc(Quality, trunc(100 * ln(1.5)));
     241        end;
     242      end
    213243      else
    214         begin
    215         Quality:=trunc(100*(ln(mi.Attack)+ln(mi.Defense)+ln(mi.Speed/150)*1.7-ln(mi.Cost)));
    216         if mi.Cap and (1 shl (mcFanatic-mcFirstNonCap))<>0 then
    217           inc(Quality,trunc(100*ln(1.5)));
    218         if mi.Cap and (1 shl (mcLongRange-mcFirstNonCap))<>0 then
    219           inc(Quality,trunc(100*ln(1.5)));
    220         end
     244      begin
     245        Category := mctGroundDefender;
     246        Quality := trunc(100 * (ln(mi.Defense) - ln(mi.Cost) * 0.6));
     247        if mi.Cap and (1 shl (mcFanatic - mcFirstNonCap)) <> 0 then
     248          Inc(Quality, trunc(100 * ln(1.5)));
     249      end;
     250    dSea:
     251      if mi.Attack = 0 then
     252      begin
     253        Category := mctTransport;
     254        if mi.TTrans = 0 then
     255          Quality := 0
     256        else
     257        begin
     258          EffectiveTransport := mi.TTrans;
     259          if EffectiveTransport > 4 then
     260            EffectiveTransport := 4; // rarely used more
     261          Quality := 100 + trunc(100 * (ln(EffectiveTransport) +
     262            ln(mi.Speed / 150) + ln(mi.Defense) - ln(mi.Cost)));
     263          if mi.Cap and (1 shl (mcNav - mcFirstNonCap)) <> 0 then
     264            Inc(Quality, trunc(100 * ln(1.5)));
     265          if mi.Cap and (1 shl (mcAirDef - mcFirstNonCap)) <> 0 then
     266            Inc(Quality, trunc(100 * ln(1.3)));
     267        end;
    221268      end
    222     else
    223       begin
    224       Category:=mctGroundDefender;
    225       Quality:=trunc(100*(ln(mi.Defense)-ln(mi.Cost)*0.6));
    226       if mi.Cap and (1 shl (mcFanatic-mcFirstNonCap))<>0 then
    227         inc(Quality,trunc(100*ln(1.5)));
    228       end;
    229   dSea:
    230     if mi.Attack=0 then
    231       begin
    232       Category:=mctTransport;
    233       if mi.TTrans=0 then Quality:=0
    234269      else
    235         begin
    236         EffectiveTransport:=mi.TTrans;
    237         if EffectiveTransport>4 then EffectiveTransport:=4; // rarely used more
    238         Quality:=100+trunc(100*(ln(EffectiveTransport)+ln(mi.Speed/150)+ln(mi.Defense)-ln(mi.Cost)));
    239         if mi.Cap and (1 shl (mcNav-mcFirstNonCap))<>0 then
    240           inc(Quality,trunc(100*ln(1.5)));
    241         if mi.Cap and (1 shl (mcAirDef-mcFirstNonCap))<>0 then
    242           inc(Quality,trunc(100*ln(1.3)));
    243         end
    244       end
    245     else
    246       begin
    247       Category:=mctCruiser;
    248       if mi.Attack=0 then Quality:=0
    249       else
    250         begin
    251         Quality:=trunc(100*(ln(mi.Attack)+ln(mi.Defense)*0.6-ln(mi.Cost)));
    252         if mi.Cap and (1 shl (mcNav-mcFirstNonCap))<>0 then
    253           inc(Quality,trunc(100*ln(1.4)));
    254         if mi.Cap and (1 shl (mcAirDef-mcFirstNonCap))<>0 then
    255           inc(Quality,trunc(100*ln(1.3)));
    256         if mi.Cap and (1 shl (mcLongRange-mcFirstNonCap))<>0 then
    257           inc(Quality,trunc(100*ln(2.0)));
    258         if mi.Cap and (1 shl (mcRadar-mcFirstNonCap))<>0 then
    259           inc(Quality,trunc(100*ln(1.5)));
    260         end
    261       end;
    262   dAir:
    263     begin
    264     Category:=mctNone;
    265     Quality:=0
    266     end;
    267   end;
    268 //!!!assert(Quality>0);
     270      begin
     271        Category := mctCruiser;
     272        if mi.Attack = 0 then
     273          Quality := 0
     274        else
     275        begin
     276          Quality := trunc(100 * (ln(mi.Attack) + ln(mi.Defense) * 0.6 - ln(mi.Cost)));
     277          if mi.Cap and (1 shl (mcNav - mcFirstNonCap)) <> 0 then
     278            Inc(Quality, trunc(100 * ln(1.4)));
     279          if mi.Cap and (1 shl (mcAirDef - mcFirstNonCap)) <> 0 then
     280            Inc(Quality, trunc(100 * ln(1.3)));
     281          if mi.Cap and (1 shl (mcLongRange - mcFirstNonCap)) <> 0 then
     282            Inc(Quality, trunc(100 * ln(2.0)));
     283          if mi.Cap and (1 shl (mcRadar - mcFirstNonCap)) <> 0 then
     284            Inc(Quality, trunc(100 * ln(1.5)));
     285        end;
     286      end;
     287    dAir:
     288    begin
     289      Category := mctNone;
     290      Quality := 0;
     291    end;
     292  end;
     293  //!!!assert(Quality>0);
    269294end;
    270295
    271296procedure TAI.RateMyModel(mix: integer; var Category, Quality: integer);
    272297var
    273 mi: TModelInfo;
     298  mi: TModelInfo;
    274299begin
    275 MakeModelInfo(me,mix,MyModel[mix],mi);
    276 RateModel(mi,Category,Quality);
     300  MakeModelInfo(me, mix, MyModel[mix], mi);
     301  RateModel(mi, Category, Quality);
    277302end;
    278303
    279304function TAI.IsBetterModel(const mi: TModelInfo): boolean;
    280305var
    281 mix,Cat,Quality,Cat1,Quality1: integer;
     306  mix, Cat, Quality, Cat1, Quality1: integer;
    282307begin
    283 RateModel(mi,Cat,Quality);
    284 for mix:=0 to RO.nModel-1 do if mi.Domain=MyModel[mix].Domain then
    285   begin
    286   RateMyModel(mix,Cat1,Quality1);
    287   if (Cat=Cat1) and (Quality<Quality1+BetterQuality[Cat])then
    288     begin result:=false; exit end
    289   end;
    290 result:=true;
     308  RateModel(mi, Cat, Quality);
     309  for mix := 0 to RO.nModel - 1 do
     310    if mi.Domain = MyModel[mix].Domain then
     311    begin
     312      RateMyModel(mix, Cat1, Quality1);
     313      if (Cat = Cat1) and (Quality < Quality1 + BetterQuality[Cat]) then
     314      begin
     315        Result := False;
     316        exit;
     317      end;
     318    end;
     319  Result := True;
    291320end;
    292321
    293322function TAI.ChooseResearchAdvance: integer;
    294323var
    295 adNext,iad,i,ad,Count,EarliestNeeded,EarliestNeeded_NoLeaveOut,
    296   NewResearch,StateOfArt,mix: integer;
    297 mi: TModelInfo;
    298 Entry: array[0..nAdv-1] of boolean;
    299 ok: boolean;
     324  adNext, iad, i, ad, Count, EarliestNeeded, EarliestNeeded_NoLeaveOut,
     325  NewResearch, StateOfArt, mix: integer;
     326  mi: TModelInfo;
     327  Entry: array[0..nAdv - 1] of boolean;
     328  ok: boolean;
    300329
    301330  function MarkEntry(ad: integer): boolean;
    302331  begin
    303   if RO.Tech[ad]>=tsApplicable then
    304     result:=false // nothing more to research here
    305   else if RO.Tech[ad]=tsSeen then
    306     begin
    307     Entry[ad]:=true;
    308     result:=true
     332    if RO.Tech[ad] >= tsApplicable then
     333      Result := False // nothing more to research here
     334    else if RO.Tech[ad] = tsSeen then
     335    begin
     336      Entry[ad] := True;
     337      Result := True;
    309338    end
    310   else
    311     begin
    312     Entry[ad]:=true;
    313     if ad=adScience then
    314       begin
    315       if MarkEntry(adTheology) then Entry[ad]:=false;
    316       if MarkEntry(adPhilosophy) then Entry[ad]:=false;
     339    else
     340    begin
     341      Entry[ad] := True;
     342      if ad = adScience then
     343      begin
     344        if MarkEntry(adTheology) then
     345          Entry[ad] := False;
     346        if MarkEntry(adPhilosophy) then
     347          Entry[ad] := False;
    317348      end
    318     else if ad=adMassProduction then
    319       begin
    320       if MarkEntry(adAutomobile) then Entry[ad]:=false;
    321       if Data.BehaviorFlags and bGender=bMale then
    322         begin if MarkEntry(adElectronics) then Entry[ad]:=false; end
    323       else begin if MarkEntry(adTheCorporation) then Entry[ad]:=false; end
     349      else if ad = adMassProduction then
     350      begin
     351        if MarkEntry(adAutomobile) then
     352          Entry[ad] := False;
     353        if Data.BehaviorFlags and bGender = bMale then
     354        begin
     355          if MarkEntry(adElectronics) then
     356            Entry[ad] := False;
     357        end
     358        else
     359        begin
     360          if MarkEntry(adTheCorporation) then
     361            Entry[ad] := False;
     362        end;
    324363      end
    325     else
    326       begin
    327       if AdvPreq[ad,0]>=0 then
    328         if MarkEntry(AdvPreq[ad,0]) then Entry[ad]:=false;
    329       if AdvPreq[ad,1]>=0 then
    330         if MarkEntry(AdvPreq[ad,1]) then Entry[ad]:=false;
    331       end;
    332     result:=true
    333     end
     364      else
     365      begin
     366        if AdvPreq[ad, 0] >= 0 then
     367          if MarkEntry(AdvPreq[ad, 0]) then
     368            Entry[ad] := False;
     369        if AdvPreq[ad, 1] >= 0 then
     370          if MarkEntry(AdvPreq[ad, 1]) then
     371            Entry[ad] := False;
     372      end;
     373      Result := True;
     374    end;
    334375  end;
    335376
    336377  procedure OptimizeDevModel(OptimizeCaps: integer);
    337378  var
    338   f,Cat,OriginalCat,Quality,BestQuality,Best: integer;
    339   mi: TModelInfo;
    340   begin
    341   MakeModelInfo(me,0,RO.DevModel,mi);
    342   RateModel(mi,OriginalCat,BestQuality);
    343   repeat
    344     Best:=-1;
    345     for f:=0 to nFeature-1 do
    346       if (1 shl f and OptimizeCaps<>0)
    347         and ((Feature[f].Preq<0) or IsResearched(Feature[f].Preq)) // check prerequisite
    348         and (RO.DevModel.Weight+Feature[f].Weight<=RO.DevModel.MaxWeight)
    349         and not((f>=mcFirstNonCap) and (RO.DevModel.Cap[f]>0)) then
    350         begin
    351         if SetNewModelFeature(f,RO.DevModel.Cap[f]+1)>=rExecuted then
     379    f, Cat, OriginalCat, Quality, BestQuality, Best: integer;
     380    mi: TModelInfo;
     381  begin
     382    MakeModelInfo(me, 0, RO.DevModel, mi);
     383    RateModel(mi, OriginalCat, BestQuality);
     384    repeat
     385      Best := -1;
     386      for f := 0 to nFeature - 1 do
     387        if (1 shl f and OptimizeCaps <> 0) and
     388          ((Feature[f].Preq < 0) or IsResearched(Feature[f].Preq)) // check prerequisite
     389          and (RO.DevModel.Weight + Feature[f].Weight <= RO.DevModel.MaxWeight) and
     390          not ((f >= mcFirstNonCap) and (RO.DevModel.Cap[f] > 0)) then
     391        begin
     392          if SetNewModelFeature(f, RO.DevModel.Cap[f] + 1) >= rExecuted then
    352393          begin
    353           MakeModelInfo(me,0,RO.DevModel,mi);
    354           RateModel(mi,Cat,Quality);
    355           assert(Cat=OriginalCat);
    356           if Quality>BestQuality then
     394            MakeModelInfo(me, 0, RO.DevModel, mi);
     395            RateModel(mi, Cat, Quality);
     396            assert(Cat = OriginalCat);
     397            if Quality > BestQuality then
    357398            begin
    358             Best:=f;
    359             BestQuality:=Quality;
     399              Best := f;
     400              BestQuality := Quality;
    360401            end;
    361           SetNewModelFeature(f,RO.DevModel.Cap[f]-1)
    362           end
    363         end;
    364     if Best>=0 then
    365       SetNewModelFeature(Best,RO.DevModel.Cap[Best]+1)
    366   until Best<0
     402            SetNewModelFeature(f, RO.DevModel.Cap[f] - 1);
     403          end;
     404        end;
     405      if Best >= 0 then
     406        SetNewModelFeature(Best, RO.DevModel.Cap[Best] + 1)
     407    until Best < 0;
    367408  end;
    368409
    369410  function LeaveOutsMissing(ad: integer): boolean;
    370411  var
    371   i: integer;
    372   begin
    373   result:=false;
    374   if RO.Tech[ad]<tsSeen then
    375     if ad in LeaveOutTechs then result:=true
    376     else if ad=adScience then
    377       begin
    378       result:=result or LeaveOutsMissing(adTheology);
    379       result:=result or LeaveOutsMissing(adPhilosophy);
     412    i: integer;
     413  begin
     414    Result := False;
     415    if RO.Tech[ad] < tsSeen then
     416      if ad in LeaveOutTechs then
     417        Result := True
     418      else if ad = adScience then
     419      begin
     420        Result := Result or LeaveOutsMissing(adTheology);
     421        Result := Result or LeaveOutsMissing(adPhilosophy);
    380422      end
    381     else if ad=adMassProduction then
    382       result:=true
    383     else for i:=0 to 1 do
    384       if AdvPreq[ad,i]>=0 then
    385         result:=result or LeaveOutsMissing(AdvPreq[ad,i]);
     423      else if ad = adMassProduction then
     424        Result := True
     425      else
     426        for i := 0 to 1 do
     427          if AdvPreq[ad, i] >= 0 then
     428            Result := Result or LeaveOutsMissing(AdvPreq[ad, i]);
    386429  end;
    387430
    388431begin
    389 if Data.BehaviorFlags and bBarbarina<>0 then
    390   begin
    391   result:=Barbarina_ChooseResearchAdvance;
    392   if result>=0 then exit
    393   end;
    394 
    395 SetAdvanceValues;
    396 
    397 // always complete traded techs first
    398 result:=-1;
    399 for ad:=0 to nAdv-1 do
    400   if (RO.Tech[ad]=tsSeen)
    401     and ((result<0) or (AdvanceValue[ad]>AdvanceValue[result])) then
    402     result:=ad;
    403 if result>=0 then exit;
    404 
    405 if Data.BehaviorFlags and bBarbarina=0 then
    406   begin
    407   // develop new model?
    408   if IsResearched(adWarriorCode) and IsResearched(adHorsebackRiding)
    409     and not ((Data.BehaviorFlags and bGender=bMale) and (RO.Tech[adIronWorking]>=tsApplicable) // wait for gunpowder
    410       and (RO.Tech[adGunPowder]<tsApplicable)) then
     432  if Data.BehaviorFlags and bBarbarina <> 0 then
     433  begin
     434    Result := Barbarina_ChooseResearchAdvance;
     435    if Result >= 0 then
     436      exit;
     437  end;
     438
     439  SetAdvanceValues;
     440
     441  // always complete traded techs first
     442  Result := -1;
     443  for ad := 0 to nAdv - 1 do
     444    if (RO.Tech[ad] = tsSeen) and ((Result < 0) or
     445      (AdvanceValue[ad] > AdvanceValue[Result])) then
     446      Result := ad;
     447  if Result >= 0 then
     448    exit;
     449
     450  if Data.BehaviorFlags and bBarbarina = 0 then
     451  begin
     452    // develop new model?
     453    if IsResearched(adWarriorCode) and IsResearched(adHorsebackRiding) and
     454      not ((Data.BehaviorFlags and bGender = bMale) and
     455      (RO.Tech[adIronWorking] >= tsApplicable) // wait for gunpowder
     456      and (RO.Tech[adGunPowder] < tsApplicable)) then
    411457    begin // check new ground models
    412     PrepareNewModel(dGround);
    413     SetNewModelFeature(mcDefense,1);
    414     SetNewModelFeature(mcOffense,2);
    415     SetNewModelFeature(mcMob,2);
    416     OptimizeDevModel(1 shl mcOffense+1 shl mcDefense+1 shl mcMob
    417       +1 shl mcLongRange+1 shl mcFanatic);
    418     MakeModelInfo(me,0,RO.DevModel,mi);
    419     if IsBetterModel(mi) then
    420       begin result:=adMilitary; exit end;
    421 
    422     PrepareNewModel(dGround);
    423     SetNewModelFeature(mcDefense,2);
    424     SetNewModelFeature(mcOffense,1);
    425     OptimizeDevModel(1 shl mcOffense+1 shl mcDefense+1 shl mcFanatic);
    426     MakeModelInfo(me,0,RO.DevModel,mi);
    427     if IsBetterModel(mi) then
    428       begin result:=adMilitary; exit end;
    429     end;
    430 
    431   if IsResearched(adMapMaking) and IsResearched(adSeafaring)
    432     and IsResearched(adNavigation) and IsResearched(adSteamEngine) then
    433     begin
    434     result:=adMilitary;
    435     for mix:=0 to RO.nModel-1 do if MyModel[mix].Cap[mcNav]>0 then result:=-1;
    436     if result=adMilitary then
    437       begin
    438       PrepareNewModel(dSea);
    439       SetNewModelFeature(mcWeapons,0);
    440       SetNewModelFeature(mcDefense,3);
    441       exit
    442       end
     458      PrepareNewModel(dGround);
     459      SetNewModelFeature(mcDefense, 1);
     460      SetNewModelFeature(mcOffense, 2);
     461      SetNewModelFeature(mcMob, 2);
     462      OptimizeDevModel(1 shl mcOffense + 1 shl mcDefense + 1 shl
     463        mcMob + 1 shl mcLongRange + 1 shl mcFanatic);
     464      MakeModelInfo(me, 0, RO.DevModel, mi);
     465      if IsBetterModel(mi) then
     466      begin
     467        Result := adMilitary;
     468        exit;
     469      end;
     470
     471      PrepareNewModel(dGround);
     472      SetNewModelFeature(mcDefense, 2);
     473      SetNewModelFeature(mcOffense, 1);
     474      OptimizeDevModel(1 shl mcOffense + 1 shl mcDefense + 1 shl mcFanatic);
     475      MakeModelInfo(me, 0, RO.DevModel, mi);
     476      if IsBetterModel(mi) then
     477      begin
     478        Result := adMilitary;
     479        exit;
     480      end;
     481    end;
     482
     483    if IsResearched(adMapMaking) and IsResearched(adSeafaring) and
     484      IsResearched(adNavigation) and IsResearched(adSteamEngine) then
     485    begin
     486      Result := adMilitary;
     487      for mix := 0 to RO.nModel - 1 do
     488        if MyModel[mix].Cap[mcNav] > 0 then
     489          Result := -1;
     490      if Result = adMilitary then
     491      begin
     492        PrepareNewModel(dSea);
     493        SetNewModelFeature(mcWeapons, 0);
     494        SetNewModelFeature(mcDefense, 3);
     495        exit;
     496      end;
    443497    end;
    444498
     
    475529  end;
    476530
    477 NewResearch:=-1;
    478 
    479 // check if cooperation with other gender doesn't work -- go for old needed techs then
    480 StateOfArt:=-1;
    481 for ad:=0 to nAdv-1 do
    482   if (RO.Tech[ad]>=tsApplicable) and (Advancedness[ad]>StateOfArt) then
    483     StateOfArt:=Advancedness[ad];
    484 EarliestNeeded:=-1;
    485 EarliestNeeded_NoLeaveOut:=-1;
    486 for ad:=0 to nAdv-1 do
    487   if (RO.Tech[ad]<tsSeen) and (AdvanceValue[ad]>=$100)
    488     and ((EarliestNeeded<0)
    489       or (Advancedness[ad]<Advancedness[EarliestNeeded])) then
    490     begin
    491     ok:=false;
    492     for iad:=0 to nResearchOrder-1 do
    493       if ResearchOrder[Data.BehaviorFlags and bGender,iad]=ad then
    494         begin ok:=true; break; end;
    495     if not ok then
    496       begin
    497       EarliestNeeded:=ad;
    498       if not LeaveOutsMissing(ad) then
    499         EarliestNeeded_NoLeaveOut:=ad;
    500       end
    501     end;
    502 if EarliestNeeded>=0 then
    503   begin
    504   if (EarliestNeeded_NoLeaveOut>=0)
    505     and (Advancedness[EarliestNeeded_NoLeaveOut]+ForceNeeded_NoLeaveOut<StateOfArt) then
    506     begin
    507     {$IFDEF DEBUG}DebugMessage(2,'No partner found, go for '
    508       +Name_Advance[EarliestNeeded_NoLeaveOut]);{$ENDIF}
    509     NewResearch:=EarliestNeeded_NoLeaveOut
     531  NewResearch := -1;
     532
     533  // check if cooperation with other gender doesn't work -- go for old needed techs then
     534  StateOfArt := -1;
     535  for ad := 0 to nAdv - 1 do
     536    if (RO.Tech[ad] >= tsApplicable) and (Advancedness[ad] > StateOfArt) then
     537      StateOfArt := Advancedness[ad];
     538  EarliestNeeded := -1;
     539  EarliestNeeded_NoLeaveOut := -1;
     540  for ad := 0 to nAdv - 1 do
     541    if (RO.Tech[ad] < tsSeen) and (AdvanceValue[ad] >= $100) and
     542      ((EarliestNeeded < 0) or (Advancedness[ad] < Advancedness[EarliestNeeded])) then
     543    begin
     544      ok := False;
     545      for iad := 0 to nResearchOrder - 1 do
     546        if ResearchOrder[Data.BehaviorFlags and bGender, iad] = ad then
     547        begin
     548          ok := True;
     549          break;
     550        end;
     551      if not ok then
     552      begin
     553        EarliestNeeded := ad;
     554        if not LeaveOutsMissing(ad) then
     555          EarliestNeeded_NoLeaveOut := ad;
     556      end;
     557    end;
     558  if EarliestNeeded >= 0 then
     559  begin
     560    if (EarliestNeeded_NoLeaveOut >= 0) and
     561      (Advancedness[EarliestNeeded_NoLeaveOut] + ForceNeeded_NoLeaveOut <
     562      StateOfArt) then
     563    begin
     564    {$IFDEF DEBUG}
     565      DebugMessage(2, 'No partner found, go for ' +
     566        Name_Advance[EarliestNeeded_NoLeaveOut]);
     567{$ENDIF}
     568      NewResearch := EarliestNeeded_NoLeaveOut;
    510569    end
    511   else if Advancedness[EarliestNeeded]+ForceNeeded_LeaveOut<StateOfArt then
    512     begin
    513     {$IFDEF DEBUG}DebugMessage(2,'No partner found, go for '
    514       +Name_Advance[EarliestNeeded]);{$ENDIF}
    515     NewResearch:=EarliestNeeded
    516     end
    517   end;
    518 
    519 // choose first directly researchable advance from own branch
    520 adNext:=-1;
    521 if NewResearch<0 then
    522   for iad:=0 to nResearchOrder-1 do
    523     begin
    524     ad:=ResearchOrder[Data.BehaviorFlags and bGender,iad];
    525     if RO.Tech[ad]<tsApplicable then
    526       begin
    527       if adNext<0 then adNext:=ad;
    528       if AdvPreq[ad,2]<>preNone then
     570    else if Advancedness[EarliestNeeded] + ForceNeeded_LeaveOut < StateOfArt then
     571    begin
     572    {$IFDEF DEBUG}
     573      DebugMessage(2, 'No partner found, go for ' + Name_Advance[EarliestNeeded]);
     574{$ENDIF}
     575      NewResearch := EarliestNeeded;
     576    end;
     577  end;
     578
     579  // choose first directly researchable advance from own branch
     580  adNext := -1;
     581  if NewResearch < 0 then
     582    for iad := 0 to nResearchOrder - 1 do
     583    begin
     584      ad := ResearchOrder[Data.BehaviorFlags and bGender, iad];
     585      if RO.Tech[ad] < tsApplicable then
     586      begin
     587        if adNext < 0 then
     588          adNext := ad;
     589        if AdvPreq[ad, 2] <> preNone then
    529590        begin // 2 of 3 required
    530         count:=0;
    531         for i:=0 to 2 do
    532           if RO.Tech[AdvPreq[ad,i]]>=tsApplicable then inc(count);
    533         if count>=2 then
    534           begin result:=ad; exit end
     591          Count := 0;
     592          for i := 0 to 2 do
     593            if RO.Tech[AdvPreq[ad, i]] >= tsApplicable then
     594              Inc(Count);
     595          if Count >= 2 then
     596          begin
     597            Result := ad;
     598            exit;
     599          end;
    535600        end
    536       else if ((AdvPreq[ad,0]=preNone) or (RO.Tech[AdvPreq[ad,0]]>=tsApplicable))
    537         and ((AdvPreq[ad,1]=preNone) or (RO.Tech[AdvPreq[ad,1]]>=tsApplicable)) then
    538         begin result:=ad; exit end
    539       end
    540     end;
    541 
    542 if NewResearch<0 then
    543   if adNext>=0 then
    544     NewResearch:=adNext // need tech from other gender
    545   else if EarliestNeeded_NoLeaveOut>=0 then
    546     NewResearch:=EarliestNeeded_NoLeaveOut // own branch complete, pick tech from other gender
    547   else if EarliestNeeded>=0 then
    548     NewResearch:=EarliestNeeded // own branch complete, pick tech from other gender
    549   else
     601        else if ((AdvPreq[ad, 0] = preNone) or
     602          (RO.Tech[AdvPreq[ad, 0]] >= tsApplicable)) and
     603          ((AdvPreq[ad, 1] = preNone) or (RO.Tech[AdvPreq[ad, 1]] >= tsApplicable)) then
     604        begin
     605          Result := ad;
     606          exit;
     607        end;
     608      end;
     609    end;
     610
     611  if NewResearch < 0 then
     612    if adNext >= 0 then
     613      NewResearch := adNext // need tech from other gender
     614    else if EarliestNeeded_NoLeaveOut >= 0 then
     615      NewResearch := EarliestNeeded_NoLeaveOut
     616    // own branch complete, pick tech from other gender
     617    else if EarliestNeeded >= 0 then
     618      NewResearch := EarliestNeeded // own branch complete, pick tech from other gender
     619    else
    550620    begin // go for future techs
    551     result:=-1;
    552     i:=0;
    553     for ad:=nAdv-4 to nAdv-1 do
    554       if (RO.Tech[ad]<MaxFutureTech) and (RO.Tech[AdvPreq[ad,0]]>=tsApplicable) then
    555         begin
    556         inc(i);
    557         if random(i)=0 then result:=ad
    558         end;
    559     assert((result<0) or AdvanceResearchable(result));
    560     exit;
    561     end;
    562 
    563 assert(NewResearch>=0);
    564 fillchar(Entry, sizeof(Entry), false);
    565 MarkEntry(NewResearch);
    566 result:=-1;
    567 for ad:=0 to nAdv-1 do
    568   if Entry[ad]
    569     and ((result<0) or (Advancedness[ad]>Advancedness[result])) then
    570     result:=ad;
    571 assert(result>=0);
     621      Result := -1;
     622      i := 0;
     623      for ad := nAdv - 4 to nAdv - 1 do
     624        if (RO.Tech[ad] < MaxFutureTech) and (RO.Tech[AdvPreq[ad, 0]] >=
     625          tsApplicable) then
     626        begin
     627          Inc(i);
     628          if random(i) = 0 then
     629            Result := ad;
     630        end;
     631      assert((Result < 0) or AdvanceResearchable(Result));
     632      exit;
     633    end;
     634
     635  assert(NewResearch >= 0);
     636  fillchar(Entry, sizeof(Entry), False);
     637  MarkEntry(NewResearch);
     638  Result := -1;
     639  for ad := 0 to nAdv - 1 do
     640    if Entry[ad] and ((Result < 0) or (Advancedness[ad] > Advancedness[Result])) then
     641      Result := ad;
     642  assert(Result >= 0);
    572643end;
    573644
    574645function TAI.ChooseStealAdvance: integer;
    575646var
    576 ad: integer;
     647  ad: integer;
    577648begin
    578 result:=-1;
    579 for ad:=0 to nAdv-1 do
    580   if AdvanceStealable(ad)
    581     and ((result<0) or (Advancedness[ad]>Advancedness[result])) then
    582     result:=ad
     649  Result := -1;
     650  for ad := 0 to nAdv - 1 do
     651    if AdvanceStealable(ad) and
     652      ((Result < 0) or (Advancedness[ad] > Advancedness[Result])) then
     653      Result := ad;
    583654end;
    584655
     
    589660
    590661const
    591 twpAllowFarmland=$0001;
    592 
    593 procedure TAI.TileWorkPlan(Loc, cix: integer;
    594   var Value, NextJob, TotalWork: integer);
     662  twpAllowFarmland = $0001;
     663
     664procedure TAI.TileWorkPlan(Loc, cix: integer; var Value, NextJob, TotalWork: integer);
    595665var
    596 OldTile,TerrType: Cardinal;
    597 TileInfo: TTileInfo;
     666  OldTile, TerrType: cardinal;
     667  TileInfo: TTileInfo;
    598668begin
    599 TotalWork:=0;
    600 NextJob:=jNone;
    601 if Map[Loc] and (fRare1 or fRare2)<>0 then
    602   begin Value:=3*8-1; exit end; // better than any tile with 2 food
    603 
    604 OldTile:=Map[Loc];
    605 TerrType:=Map[Loc] and fTerrain;
    606 if (TerrType>=fGrass) then
    607   begin
    608   if Map[Loc] and fPoll<>0 then
     669  TotalWork := 0;
     670  NextJob := jNone;
     671  if Map[Loc] and (fRare1 or fRare2) <> 0 then
     672  begin
     673    Value := 3 * 8 - 1;
     674    exit;
     675  end; // better than any tile with 2 food
     676
     677  OldTile := Map[Loc];
     678  TerrType := Map[Loc] and fTerrain;
     679  if (TerrType >= fGrass) then
     680  begin
     681    if Map[Loc] and fPoll <> 0 then
    609682    begin // clean pollution
    610     if NextJob=jNone then NextJob:=jPoll;
    611     inc(TotalWork,PollWork);
    612     Map[Loc]:=Map[Loc] and not fPoll;
    613     end;
    614   if Map[Loc] and (fTerrain or fSpecial)=fSwamp then
     683      if NextJob = jNone then
     684        NextJob := jPoll;
     685      Inc(TotalWork, PollWork);
     686      Map[Loc] := Map[Loc] and not fPoll;
     687    end;
     688    if Map[Loc] and (fTerrain or fSpecial) = fSwamp then
    615689    begin // drain swamp
    616     if NextJob=jNone then NextJob:=jClear;
    617     inc(TotalWork,Terrain[TerrType].IrrClearWork);
    618     Map[Loc]:=Map[Loc] and not fTerrain or fGrass;
    619     TerrType:=fGrass;
    620     Map[Loc]:=Map[Loc] or
    621       Cardinal(SpecialTile(Loc,TerrType,G.lx) shl 5);
     690      if NextJob = jNone then
     691        NextJob := jClear;
     692      Inc(TotalWork, Terrain[TerrType].IrrClearWork);
     693      Map[Loc] := Map[Loc] and not fTerrain or fGrass;
     694      TerrType := fGrass;
     695      Map[Loc] := Map[Loc] or cardinal(SpecialTile(Loc, TerrType, G.lx) shl 5);
    622696    end
    623   else if IsResearched(adExplosives)
    624     and (Map[Loc] and (fTerrain or fSpecial) in [fTundra,fHills])
    625     and (Map[Loc] and fTerImp<>tiMine)
    626     and (SpecialTile(Loc,fHills,G.lx)=0) then
     697    else if IsResearched(adExplosives) and
     698      (Map[Loc] and (fTerrain or fSpecial) in [fTundra, fHills]) and
     699      (Map[Loc] and fTerImp <> tiMine) and (SpecialTile(Loc, fHills, G.lx) = 0) then
    627700    begin // transform
    628     if NextJob=jNone then NextJob:=jTrans;
    629     inc(TotalWork,Terrain[TerrType].TransWork);
    630     Map[Loc]:=Map[Loc] and not fTerrain or fGrass;
    631     TerrType:=fGrass;
    632     Map[Loc]:=Map[Loc] or
    633       Cardinal(SpecialTile(Loc,TerrType,G.lx) shl 5);
    634     end;
    635   if (Terrain[TerrType].MineEff>0) and (RO.Government<>gDespotism) then
    636     begin
    637     if Map[Loc] and fTerImp<>tiMine then
     701      if NextJob = jNone then
     702        NextJob := jTrans;
     703      Inc(TotalWork, Terrain[TerrType].TransWork);
     704      Map[Loc] := Map[Loc] and not fTerrain or fGrass;
     705      TerrType := fGrass;
     706      Map[Loc] := Map[Loc] or cardinal(SpecialTile(Loc, TerrType, G.lx) shl 5);
     707    end;
     708    if (Terrain[TerrType].MineEff > 0) and (RO.Government <> gDespotism) then
     709    begin
     710      if Map[Loc] and fTerImp <> tiMine then
    638711      begin // add mine
    639       if NextJob=jNone then NextJob:=jMine;
    640       inc(TotalWork,Terrain[TerrType].MineAfforestWork);
    641       Map[Loc]:=Map[Loc] and not fTerImp or tiMine;
     712        if NextJob = jNone then
     713          NextJob := jMine;
     714        Inc(TotalWork, Terrain[TerrType].MineAfforestWork);
     715        Map[Loc] := Map[Loc] and not fTerImp or tiMine;
     716      end;
     717    end
     718    else if Terrain[TerrType].IrrEff > 0 then
     719    begin
     720      if Map[Loc] and fTerImp = tiIrrigation then
     721      begin // add farmland
     722        if (MyCity[cix].Built[imSupermarket] > 0) and
     723          IsResearched(adRefrigeration) and (RO.Government <> gDespotism) then
     724        begin
     725          if NextJob = jNone then
     726            NextJob := jFarm;
     727          Inc(TotalWork, Terrain[TerrType].IrrClearWork * FarmWork);
     728          Map[Loc] := Map[Loc] and not fTerImp or tiFarm;
     729        end;
    642730      end
    643     end
    644   else if Terrain[TerrType].IrrEff>0 then
    645     begin
    646     if Map[Loc] and fTerImp=tiIrrigation then
    647       begin // add farmland
    648       if (MyCity[cix].Built[imSupermarket]>0) and IsResearched(adRefrigeration)
    649         and (RO.Government<>gDespotism) then
    650         begin
    651         if NextJob=jNone then NextJob:=jFarm;
    652         inc(TotalWork,Terrain[TerrType].IrrClearWork*FarmWork);
    653         Map[Loc]:=Map[Loc] and not fTerImp or tiFarm;
    654         end
    655       end
    656     else if Map[Loc] and fTerImp<>tiFarm then
     731      else if Map[Loc] and fTerImp <> tiFarm then
    657732      begin // add irrigation
    658       if (RO.Government<>gDespotism)
    659         or (Map[Loc] and (fTerrain or fSpecial)<>fGrass) then
    660         begin
    661         if NextJob=jNone then NextJob:=jIrr;
    662         inc(TotalWork,Terrain[TerrType].IrrClearWork);
    663         Map[Loc]:=Map[Loc] and not fTerImp or tiIrrigation;
    664         end
    665       end
    666     end;
    667   if (Terrain[TerrType].MoveCost=1)
    668     and (Map[Loc] and (fRoad or fRR)=0)
    669     and ((Map[Loc] and fRiver=0) or IsResearched(adBridgeBuilding)) then
     733        if (RO.Government <> gDespotism) or
     734          (Map[Loc] and (fTerrain or fSpecial) <> fGrass) then
     735        begin
     736          if NextJob = jNone then
     737            NextJob := jIrr;
     738          Inc(TotalWork, Terrain[TerrType].IrrClearWork);
     739          Map[Loc] := Map[Loc] and not fTerImp or tiIrrigation;
     740        end;
     741      end;
     742    end;
     743    if (Terrain[TerrType].MoveCost = 1) and (Map[Loc] and (fRoad or fRR) = 0) and
     744      ((Map[Loc] and fRiver = 0) or IsResearched(adBridgeBuilding)) then
    670745    begin // add road
    671     if NextJob=jNone then NextJob:=jRoad;
    672     inc(TotalWork,RoadWork);
    673     Map[Loc]:=Map[Loc] or fRoad;
    674     end;
    675   if ((Map[Loc] and fTerImp=tiMine)
    676       or (Terrain[TerrType].ProdRes[Map[Loc] shr 5 and 3]>=2))
    677     and IsResearched(adRailroad)
    678     and (Map[Loc] and fRR=0)
    679     and ((Map[Loc] and fRiver=0) or IsResearched(adBridgeBuilding))
    680     and (RO.Government<>gDespotism) then
     746      if NextJob = jNone then
     747        NextJob := jRoad;
     748      Inc(TotalWork, RoadWork);
     749      Map[Loc] := Map[Loc] or fRoad;
     750    end;
     751    if ((Map[Loc] and fTerImp = tiMine) or
     752      (Terrain[TerrType].ProdRes[Map[Loc] shr 5 and 3] >= 2)) and
     753      IsResearched(adRailroad) and (Map[Loc] and fRR = 0) and
     754      ((Map[Loc] and fRiver = 0) or IsResearched(adBridgeBuilding)) and
     755      (RO.Government <> gDespotism) then
    681756    begin // add railroad
    682     if Map[Loc] and fRoad=0 then
    683       begin
    684       if NextJob=jNone then NextJob:=jRoad;
    685       inc(TotalWork,RoadWork*Terrain[TerrType].MoveCost);
    686       end;
    687     if NextJob=jNone then NextJob:=jRR;
    688     inc(TotalWork,RRWork*Terrain[TerrType].MoveCost);
    689     Map[Loc]:=Map[Loc] and not fRoad or fRR;
    690     end;
    691   end;
    692 Server(sGetTileInfo,me,Loc,TileInfo);
    693 Value:=TileInfo.Food*8+TileInfo.Prod*2+TileInfo.Trade;
    694 Map[Loc]:=OldTile;
     757      if Map[Loc] and fRoad = 0 then
     758      begin
     759        if NextJob = jNone then
     760          NextJob := jRoad;
     761        Inc(TotalWork, RoadWork * Terrain[TerrType].MoveCost);
     762      end;
     763      if NextJob = jNone then
     764        NextJob := jRR;
     765      Inc(TotalWork, RRWork * Terrain[TerrType].MoveCost);
     766      Map[Loc] := Map[Loc] and not fRoad or fRR;
     767    end;
     768  end;
     769  Server(sGetTileInfo, me, Loc, TileInfo);
     770  Value := TileInfo.Food * 8 + TileInfo.Prod * 2 + TileInfo.Trade;
     771  Map[Loc] := OldTile;
    695772end;
    696773
     
    698775procedure TAI.ProcessSettlers;
    699776var
    700 i,uix,cix,ecix,dtr,Loc,RadiusLoc,Special,Food,Prod,Trade,CityFood,Happy,
    701   TestScore,BestNearCityScore,BestUnusedValue,BestUnusedLoc,
    702   Value,NextJob,TotalWork,V21,part,Loc1: integer;
    703 Tile: Cardinal;
    704 FoodOk,Started: boolean;
    705 Radius: TVicinity21Loc;
    706 CityAreaInfo: TCityAreaInfo;
    707 TileFood, ResourceScore, CityScore: array[0..lxmax*lymax-1] of integer;
    708 
    709   procedure AddJob(Loc,Job,Score: integer);
     777  i, uix, cix, ecix, dtr, Loc, RadiusLoc, Special, Food, Prod, Trade,
     778  CityFood, Happy, TestScore, BestNearCityScore, BestUnusedValue,
     779  BestUnusedLoc, Value, NextJob, TotalWork, V21, part, Loc1: integer;
     780  Tile: cardinal;
     781  FoodOk, Started: boolean;
     782  Radius: TVicinity21Loc;
     783  CityAreaInfo: TCityAreaInfo;
     784  TileFood, ResourceScore, CityScore: array[0..lxmax * lymax - 1] of integer;
     785
     786  procedure AddJob(Loc, Job, Score: integer);
    710787  // set Score=1 for low-priority jobs
    711788  begin
    712   JobAssignment_AddJob(Loc,Job,Score);
    713   if (Score>1) and (District[Loc]>=0) and (District[Loc]<maxCOD) then
    714     dec(SettlerSurplus[District[Loc]]);
     789    JobAssignment_AddJob(Loc, Job, Score);
     790    if (Score > 1) and (District[Loc] >= 0) and (District[Loc] < maxCOD) then
     791      Dec(SettlerSurplus[District[Loc]]);
    715792  end;
    716793
    717794  procedure ReserveCityRadius(Loc: integer);
    718795  var
    719   V21,RadiusLoc: integer;
    720   Radius: TVicinity21Loc;
    721   begin
    722   V21_to_Loc(Loc,Radius);
    723   for V21:=1 to 26 do
    724     begin
    725     RadiusLoc:=Radius[V21];
    726     if (RadiusLoc>=0) then
    727       begin
    728       ResourceScore[RadiusLoc]:=0;
    729       TileFood[RadiusLoc]:=0;
    730       end
    731     end
     796    V21, RadiusLoc: integer;
     797    Radius: TVicinity21Loc;
     798  begin
     799    V21_to_Loc(Loc, Radius);
     800    for V21 := 1 to 26 do
     801    begin
     802      RadiusLoc := Radius[V21];
     803      if (RadiusLoc >= 0) then
     804      begin
     805        ResourceScore[RadiusLoc] := 0;
     806        TileFood[RadiusLoc] := 0;
     807      end;
     808    end;
    732809  end;
    733810
    734811  procedure ScoreRoadConnections;
    735812  var
    736   V8,nFragments,Loc,Loc1,History,RoadScore,a,b,FullyDeveloped,ConnectMask: integer;
    737   BridgeOk: boolean;
    738   Adjacent: TVicinity8Loc;
    739   begin
    740   BridgeOk:= IsResearched(adBridgeBuilding);
    741   if IsResearched(adRailroad) then FullyDeveloped:=fRR or fCity
    742   else FullyDeveloped:=fRoad or fRR or fCity;
    743   for Loc:=G.lx to G.lx*(G.ly-1)-1 do
    744     if ((1 shl (Map[Loc] and fTerrain)) and (1 shl fOcean or 1 shl fShore or 1 shl fDesert or 1 shl fArctic or 1 shl fUNKNOWN)=0)
    745       and (RO.Territory[Loc]=me)
    746       and (Map[Loc] and FullyDeveloped=0)
    747       and (BridgeOk or (Map[Loc] and fRiver=0)) then
    748       begin
    749       nFragments:=0;
    750       History:=0;
    751       if Map[Loc] and fRoad<>0 then ConnectMask:=fRR or fCity // check for railroad
    752       else ConnectMask:=fRoad or fRR or fCity; // check for road
    753       V8_to_Loc(Loc,Adjacent);
    754       for V8:=0 to 9 do
    755         begin
    756         Loc1:=Adjacent[V8 and 7];
    757         History:=History shl 1;
    758         if (Loc1>=0) and (RO.Territory[Loc1]=me)
    759           and (Map[Loc1] and ConnectMask<>0) then
     813    V8, nFragments, Loc, Loc1, History, RoadScore, a, b, FullyDeveloped,
     814    ConnectMask: integer;
     815    BridgeOk: boolean;
     816    Adjacent: TVicinity8Loc;
     817  begin
     818    BridgeOk := IsResearched(adBridgeBuilding);
     819    if IsResearched(adRailroad) then
     820      FullyDeveloped := fRR or fCity
     821    else
     822      FullyDeveloped := fRoad or fRR or fCity;
     823    for Loc := G.lx to G.lx * (G.ly - 1) - 1 do
     824      if ((1 shl (Map[Loc] and fTerrain)) and (1 shl fOcean or 1 shl
     825        fShore or 1 shl fDesert or 1 shl fArctic or 1 shl fUNKNOWN) = 0) and
     826        (RO.Territory[Loc] = me) and (Map[Loc] and FullyDeveloped = 0) and
     827        (BridgeOk or (Map[Loc] and fRiver = 0)) then
     828      begin
     829        nFragments := 0;
     830        History := 0;
     831        if Map[Loc] and fRoad <> 0 then
     832          ConnectMask := fRR or fCity // check for railroad
     833        else
     834          ConnectMask := fRoad or fRR or fCity; // check for road
     835        V8_to_Loc(Loc, Adjacent);
     836        for V8 := 0 to 9 do
     837        begin
     838          Loc1 := Adjacent[V8 and 7];
     839          History := History shl 1;
     840          if (Loc1 >= 0) and (RO.Territory[Loc1] = me) and
     841            (Map[Loc1] and ConnectMask <> 0) then
    760842          begin
    761           inc(History);
    762           if V8>=2 then
     843            Inc(History);
     844            if V8 >= 2 then
    763845            begin
    764             inc(nFragments);
    765             case V8 and 1 of
    766               0:
    767                 if History and 6<>0 then
    768                   dec(nFragments);
    769               1:
    770                 if History and 2<>0 then
    771                   dec(nFragments)
    772                 else if History and 4<>0 then
     846              Inc(nFragments);
     847              case V8 and 1 of
     848                0:
     849                  if History and 6 <> 0 then
     850                    Dec(nFragments);
     851                1:
     852                  if History and 2 <> 0 then
     853                    Dec(nFragments)
     854                  else if History and 4 <> 0 then
    773855                  begin
    774                   V8_to_ab((V8-1) and 7,a,b);
    775                   ab_to_Loc(Loc,a shl 1,b shl 1,Loc1);
    776                   if (Loc1>=0)
    777                     and (Map[Loc1] and ConnectMask<>0) then
    778                     dec(nFragments)
     856                    V8_to_ab((V8 - 1) and 7, a, b);
     857                    ab_to_Loc(Loc, a shl 1, b shl 1, Loc1);
     858                    if (Loc1 >= 0) and (Map[Loc1] and ConnectMask <> 0) then
     859                      Dec(nFragments);
    779860                  end
    780               end
     861              end;
    781862            end;
    782863          end;
    783864        end;
    784       if nFragments>=2 then // road or railroad connection desirable
    785         begin
    786         if Map[Loc] and fRiver<>0 then RoadScore:=44+(nFragments-2)*4
    787         else RoadScore:=56-Terrain[Map[Loc] and fTerrain].MoveCost*4
    788           +(nFragments-2)*4;
    789         if Map[Loc] and fRoad<>0 then
    790           AddJob(Loc, jRR, RoadScore)
    791         else AddJob(Loc, jRoad, RoadScore)
     865        if nFragments >= 2 then // road or railroad connection desirable
     866        begin
     867          if Map[Loc] and fRiver <> 0 then
     868            RoadScore := 44 + (nFragments - 2) * 4
     869          else
     870            RoadScore := 56 - Terrain[Map[Loc] and fTerrain].MoveCost * 4 +
     871              (nFragments - 2) * 4;
     872          if Map[Loc] and fRoad <> 0 then
     873            AddJob(Loc, jRR, RoadScore)
     874          else
     875            AddJob(Loc, jRoad, RoadScore);
    792876        end;
    793877      end;
     
    795879
    796880begin
    797 fillchar(SettlerSurplus, sizeof(SettlerSurplus), 0);
    798 JobAssignment_Initialize;
    799 
    800 if (Data.BehaviorFlags and bBarbarina=0) or (RO.nCity<3) then
    801   begin
    802   fillchar(TileFood,sizeof(TileFood),0);
    803   fillchar(ResourceScore,sizeof(ResourceScore),0);
    804   for Loc:=0 to MapSize-1 do
    805     if Map[Loc] and fTerrain<>fUNKNOWN then
    806       if Map[Loc] and fDeadLands<>0 then
    807         begin
    808         if not IsResearched(adMassProduction) or (Map[Loc] and fModern<>0) then
    809           ResourceScore[Loc]:=20;
     881  fillchar(SettlerSurplus, sizeof(SettlerSurplus), 0);
     882  JobAssignment_Initialize;
     883
     884  if (Data.BehaviorFlags and bBarbarina = 0) or (RO.nCity < 3) then
     885  begin
     886    fillchar(TileFood, sizeof(TileFood), 0);
     887    fillchar(ResourceScore, sizeof(ResourceScore), 0);
     888    for Loc := 0 to MapSize - 1 do
     889      if Map[Loc] and fTerrain <> fUNKNOWN then
     890        if Map[Loc] and fDeadLands <> 0 then
     891        begin
     892          if not IsResearched(adMassProduction) or (Map[Loc] and fModern <> 0) then
     893            ResourceScore[Loc] := 20;
    810894        end
    811       else if Map[Loc] and fTerrain=fGrass then
    812         TileFood[Loc]:=Terrain[fGrass].FoodRes[Map[Loc] shr 5 and 3]-1
    813       else
    814         begin
    815         Special:=SpecialTile(Loc,Map[Loc] and fTerrain,G.lx);
    816         if Special<>0 then with Terrain[Map[Loc] and fTerrain] do
     895        else if Map[Loc] and fTerrain = fGrass then
     896          TileFood[Loc] := Terrain[fGrass].FoodRes[Map[Loc] shr 5 and 3] - 1
     897        else
     898        begin
     899          Special := SpecialTile(Loc, Map[Loc] and fTerrain, G.lx);
     900          if Special <> 0 then
     901            with Terrain[Map[Loc] and fTerrain] do
     902            begin
     903              Food := FoodRes[Special];
     904              if MineEff = 0 then
     905                Inc(Food, IrrEff);
     906              Prod := ProdRes[Special] + MineEff;
     907              Trade := TradeRes[Special];
     908              if MoveCost = 1 then
     909                Inc(Trade);
     910              ResourceScore[Loc] := Food + 2 * Prod + Trade - 7;
     911              if Food > 2 then
     912                TileFood[Loc] := Food - 2;
     913            end;
     914        end;
     915
     916    for cix := 0 to RO.nCity - 1 do
     917      if MyCity[cix].Loc >= 0 then
     918        ReserveCityRadius(MyCity[cix].Loc); // these resources already have a city
     919    for uix := 0 to RO.nUn - 1 do
     920      if (MyUnit[uix].Loc >= 0) and (MyUnit[uix].Job = jCity) then
     921        ReserveCityRadius(MyUnit[uix].Loc); // these resources almost already have a city
     922    for ecix := 0 to RO.nEnemyCity - 1 do
     923      if RO.EnemyCity[ecix].Loc >= 0 then
     924        ReserveCityRadius(RO.EnemyCity[ecix].Loc);
     925    // these resources already have an enemy city
     926
     927    // rate possible new cities
     928    fillchar(CityScore, MapSize * sizeof(integer), 0);
     929    for Loc := 0 to MapSize - 1 do
     930    begin
     931      FoodOk := (TileFood[Loc] > 0) and
     932        ((Map[Loc] and fTerrain = fGrass) and
     933        ((RO.Government <> gDespotism) or (Map[Loc] and fSpecial = fSpecial1)) or
     934        (Map[Loc] and (fTerrain or fSpecial) = fPrairie or fSpecial1));
     935      if FoodOk and ((RO.Territory[Loc] < 0) or (RO.Territory[Loc] = me)) then
     936      begin
     937        TestScore := 0;
     938        CityFood := 0;
     939        BestNearCityScore := 0;
     940        V21_to_Loc(Loc, Radius);
     941        for V21 := 1 to 26 do
     942        begin // sum resource scores in potential city radius
     943          RadiusLoc := Radius[V21];
     944          if (RadiusLoc >= 0) then
    817945          begin
    818           Food:=FoodRes[Special];
    819           if MineEff=0 then inc(Food,IrrEff);
    820           Prod:=ProdRes[Special]+MineEff;
    821           Trade:=TradeRes[Special];
    822           if MoveCost=1 then inc(Trade);
    823           ResourceScore[Loc]:=Food+2*Prod+Trade-7;
    824           if Food>2 then TileFood[Loc]:=Food-2;
    825           end
    826         end;
    827 
    828   for cix:=0 to RO.nCity-1 do
    829     if MyCity[cix].Loc>=0 then
    830       ReserveCityRadius(MyCity[cix].Loc); // these resources already have a city
    831   for uix:=0 to RO.nUn-1 do
    832     if (MyUnit[uix].Loc>=0) and (MyUnit[uix].Job=jCity) then
    833       ReserveCityRadius(MyUnit[uix].Loc); // these resources almost already have a city
    834   for ecix:=0 to RO.nEnemyCity-1 do
    835     if RO.EnemyCity[ecix].Loc>=0 then
    836       ReserveCityRadius(RO.EnemyCity[ecix].Loc); // these resources already have an enemy city
    837 
    838   // rate possible new cities
    839   fillchar(CityScore, MapSize*sizeof(integer), 0);
    840   for Loc:=0 to MapSize-1 do
    841     begin
    842     FoodOk:= (TileFood[Loc]>0)
    843       and ((Map[Loc] and fTerrain=fGrass)
    844           and ((RO.Government<>gDespotism) or (Map[Loc] and fSpecial=fSpecial1))
    845         or (Map[Loc] and (fTerrain or fSpecial)=fPrairie or fSpecial1));
    846     if FoodOk and ((RO.Territory[Loc]<0) or (RO.Territory[Loc]=me)) then
    847       begin
    848       TestScore:=0;
    849       CityFood:=0;
    850       BestNearCityScore:=0;
    851       V21_to_Loc(Loc,Radius);
    852       for V21:=1 to 26 do
    853         begin // sum resource scores in potential city radius
    854         RadiusLoc:=Radius[V21];
    855         if (RadiusLoc>=0) then
    856           begin
    857           inc(CityFood,TileFood[RadiusLoc]);
    858           if ResourceScore[RadiusLoc]>0 then
    859             inc(TestScore,ResourceScore[RadiusLoc]);
    860           if CityScore[RadiusLoc]>BestNearCityScore then
    861             BestNearCityScore:=CityScore[RadiusLoc]
    862           end
    863         end;
    864       if CityFood>=MinCityFood then // city is worth founding
    865         begin
    866         TestScore:=(72+2*TestScore) shl 8 + ((loc xor me)*4567) mod 251;
     946            Inc(CityFood, TileFood[RadiusLoc]);
     947            if ResourceScore[RadiusLoc] > 0 then
     948              Inc(TestScore, ResourceScore[RadiusLoc]);
     949            if CityScore[RadiusLoc] > BestNearCityScore then
     950              BestNearCityScore := CityScore[RadiusLoc];
     951          end;
     952        end;
     953        if CityFood >= MinCityFood then // city is worth founding
     954        begin
     955          TestScore := (72 + 2 * TestScore) shl 8 + ((loc xor me) * 4567) mod 251;
    867956          // some unexactness, random but always the same for this tile
    868         if TestScore>BestNearCityScore then
     957          if TestScore > BestNearCityScore then
    869958          begin // better than all other sites in radius
    870           if BestNearCityScore>0 then // found no other cities in radius
     959            if BestNearCityScore > 0 then // found no other cities in radius
    871960            begin
    872             for V21:=1 to 26 do
     961              for V21 := 1 to 26 do
    873962              begin
    874               RadiusLoc:=Radius[V21];
    875               if (RadiusLoc>=0) then
    876                 CityScore[RadiusLoc]:=0;
     963                RadiusLoc := Radius[V21];
     964                if (RadiusLoc >= 0) then
     965                  CityScore[RadiusLoc] := 0;
    877966              end;
    878967            end;
    879           CityScore[Loc]:=TestScore
     968            CityScore[Loc] := TestScore;
    880969          end;
    881         end
    882       end;
    883     end;
    884   for Loc:=0 to MapSize-1 do
    885     if CityScore[Loc]>0 then
    886       AddJob(Loc, jCity, CityScore[Loc] shr 8);
    887   end;
    888 
    889 // improve terrain
    890 for cix:=0 to RO.nCity-1 do with MyCity[cix] do if Loc>=0 then
    891   begin // order terrain improvements
    892   BestUnusedValue:=0;
    893   City_GetAreaInfo(cix,CityAreaInfo);
    894   V21_to_Loc(Loc,Radius);
    895   for V21:=1 to 26 do if V21<>CityOwnTile then
    896     if 1 shl V21 and Tiles<>0 then
    897       begin // tile is being exploited!
    898       RadiusLoc:=Radius[V21];
    899       if not (Map[RadiusLoc] and fTerrain in [fDesert,fArctic]) then
    900         begin
    901         assert(RadiusLoc>=0);
    902         TileWorkPlan(RadiusLoc,cix,Value,NextJob,TotalWork);
    903         if (NextJob=jRoad)
    904           and (Built[imPalace]+Built[imCourt]+Built[imTownHall]=0) then
    905           AddJob(RadiusLoc, NextJob, 44)
    906         else if NextJob<>jNone then
    907           AddJob(RadiusLoc, NextJob, 84)
    908         end
    909       end
    910     else if CityAreaInfo.Available[V21]=faAvailable then
    911       begin // tile could be exploited
    912       RadiusLoc:=Radius[V21];
    913       assert(RadiusLoc>=0);
    914       if not (Map[RadiusLoc] and fTerrain in [fDesert,fArctic]) then
    915         begin
    916         TileWorkPlan(RadiusLoc,cix,Value,NextJob,TotalWork);
    917         Value:=Value shl 16 +$FFFF-TotalWork;
    918         if Value>BestUnusedValue then
     970        end;
     971      end;
     972    end;
     973    for Loc := 0 to MapSize - 1 do
     974      if CityScore[Loc] > 0 then
     975        AddJob(Loc, jCity, CityScore[Loc] shr 8);
     976  end;
     977
     978  // improve terrain
     979  for cix := 0 to RO.nCity - 1 do
     980    with MyCity[cix] do
     981      if Loc >= 0 then
     982      begin // order terrain improvements
     983        BestUnusedValue := 0;
     984        City_GetAreaInfo(cix, CityAreaInfo);
     985        V21_to_Loc(Loc, Radius);
     986        for V21 := 1 to 26 do
     987          if V21 <> CityOwnTile then
     988            if 1 shl V21 and Tiles <> 0 then
     989            begin // tile is being exploited!
     990              RadiusLoc := Radius[V21];
     991              if not (Map[RadiusLoc] and fTerrain in [fDesert, fArctic]) then
     992              begin
     993                assert(RadiusLoc >= 0);
     994                TileWorkPlan(RadiusLoc, cix, Value, NextJob, TotalWork);
     995                if (NextJob = jRoad) and (Built[imPalace] +
     996                  Built[imCourt] + Built[imTownHall] = 0) then
     997                  AddJob(RadiusLoc, NextJob, 44)
     998                else if NextJob <> jNone then
     999                  AddJob(RadiusLoc, NextJob, 84);
     1000              end;
     1001            end
     1002            else if CityAreaInfo.Available[V21] = faAvailable then
     1003            begin // tile could be exploited
     1004              RadiusLoc := Radius[V21];
     1005              assert(RadiusLoc >= 0);
     1006              if not (Map[RadiusLoc] and fTerrain in [fDesert, fArctic]) then
     1007              begin
     1008                TileWorkPlan(RadiusLoc, cix, Value, NextJob, TotalWork);
     1009                Value := Value shl 16 + $FFFF - TotalWork;
     1010                if Value > BestUnusedValue then
     1011                begin
     1012                  BestUnusedValue := Value;
     1013                  BestUnusedLoc := RadiusLoc;
     1014                end;
     1015              end;
     1016            end;
     1017        if BestUnusedValue > 0 then
     1018        begin
     1019          TileWorkPlan(BestUnusedLoc, cix, Value, NextJob, TotalWork);
     1020          if NextJob <> jNone then
     1021            AddJob(BestUnusedLoc, NextJob, 44);
     1022        end;
     1023      end;
     1024
     1025  ScoreRoadConnections;
     1026
     1027  if Data.BehaviorFlags and bBarbarina = 0 then // low priority jobs
     1028    for Loc := 0 to MapSize - 1 do
     1029      if RO.Territory[Loc] = me then
     1030      begin
     1031        Tile := Map[Loc];
     1032        if Tile and fPoll <> 0 then
     1033          AddJob(Loc, jPoll, 1)
     1034        else
     1035          case Tile and (fTerrain or fSpecial or fCity) of
     1036            fGrass, fGrass + fSpecial1:
     1037              if IsResearched(adExplosives) and (SpecialTile(Loc, fHills, G.lx) > 0) then
     1038                AddJob(Loc, jTrans, 1);
     1039            fSwamp:
     1040              if SpecialTile(Loc, fSwamp, G.lx) = 0 then
     1041                AddJob(Loc, jClear, 1);
     1042            fTundra, fHills:
     1043              if IsResearched(adExplosives) and (Tile and fTerImp <> tiMine) and
     1044                (SpecialTile(Loc, fHills, G.lx) = 0) then
     1045                AddJob(Loc, jTrans, 1);
     1046          end;
     1047      end;
     1048
     1049  // cities for colony ship production
     1050  if Data.BehaviorFlags and bBarbarina = bBarbarina then
     1051  begin
     1052    for part := 0 to nShipPart - 1 do
     1053      for i := 0 to ColonyShipPlan[part].nLocFoundCity - 1 do
     1054      begin
     1055        Loc := ColonyShipPlan[part].LocFoundCity[i];
     1056        Started := False;
     1057        for uix := 0 to RO.nUn - 1 do
     1058          if (MyUnit[uix].Loc = Loc) and (MyUnit[uix].Job = jCity) then
    9191059          begin
    920           BestUnusedValue:=Value;
    921           BestUnusedLoc:=RadiusLoc;
     1060            Started := True;
     1061            break;
     1062          end;
     1063        if not Started then
     1064        begin
     1065          Tile := RO.Map[Loc];
     1066          if (Tile and fTerrain = fForest) or (Tile and fTerrain = fSwamp) then
     1067            AddJob(Loc, jClear, 235)
     1068          else if Tile and fTerrain = fHills then
     1069          begin
     1070            if IsResearched(adExplosives) then
     1071              AddJob(Loc, jTrans, 235);
    9221072          end
    923         end
    924       end;
    925   if BestUnusedValue>0 then
    926     begin
    927     TileWorkPlan(BestUnusedLoc,cix,Value,NextJob,TotalWork);
    928     if NextJob<>jNone then
    929       AddJob(BestUnusedLoc, NextJob, 44)
    930     end
    931   end;
    932 
    933 ScoreRoadConnections;
    934 
    935 if Data.BehaviorFlags and bBarbarina=0 then // low priority jobs
    936   for Loc:=0 to MapSize-1 do if RO.Territory[Loc]=me then
    937     begin
    938     Tile:=Map[Loc];
    939     if Tile and fPoll<>0 then
    940       AddJob(Loc, jPoll, 1)
    941     else case Tile and (fTerrain or fSpecial or fCity) of
    942       fGrass, fGrass+fSpecial1:
    943         if IsResearched(adExplosives) and (SpecialTile(Loc,fHills,G.lx)>0) then
    944           AddJob(Loc, jTrans, 1);
    945       fSwamp:
    946         if SpecialTile(Loc,fSwamp,G.lx)=0 then
    947           AddJob(Loc, jClear, 1);
    948       fTundra,fHills:
    949         if IsResearched(adExplosives) and (Tile and fTerImp<>tiMine)
    950           and (SpecialTile(Loc,fHills,G.lx)=0) then
    951           AddJob(Loc, jTrans, 1);
    952       end
    953     end;
    954 
    955 // cities for colony ship production
    956 if Data.BehaviorFlags and bBarbarina=bBarbarina then
    957   begin
    958   for part:=0 to nShipPart-1 do
    959     for i:=0 to ColonyShipPlan[part].nLocFoundCity-1 do
    960       begin
    961       Loc:=ColonyShipPlan[part].LocFoundCity[i];
    962       Started:=false;
    963       for uix:=0 to RO.nUn-1 do
    964         if (MyUnit[uix].Loc=Loc) and (MyUnit[uix].Job=jCity) then
    965           begin
    966           Started:=true;
    967           break
    968           end;
    969       if not Started then
    970         begin
    971         Tile:=RO.Map[Loc];
    972         if (Tile and fTerrain=fForest) or (Tile and fTerrain=fSwamp) then
    973           AddJob(Loc,jClear,235)
    974         else if Tile and fTerrain=fHills then
    975           begin
    976           if IsResearched(adExplosives) then
    977             AddJob(Loc,jTrans,235)
    978           end
    979         else AddJob(Loc,jCity,235);
    980         end;
    981       V21_to_Loc(Loc, Radius);
    982       for V21:=1 to 26 do
    983         begin
    984         Loc1:=Radius[V21];
    985         if (Loc1>=0) and (RO.Map[Loc1] and (fTerrain or fSpecial)=fSwamp) then
    986           AddJob(Loc1,jClear,255);
    987         end
    988       end
    989   end;
    990 
    991 // choose all settlers to work
    992 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    993   if (Loc>=0) and ((mix=mixSettlers) or (mix=mixSlaves)
    994     or (Data.BehaviorFlags and bBarbarina<>0) and (MyModel[mix].Kind=mkSettler)) then
    995     begin
    996     JobAssignment_AddUnit(uix);
    997     if (District[Loc]>=0) and (District[Loc]<maxCOD) then
    998       inc(SettlerSurplus[District[Loc]]);
    999     end;
    1000 
    1001 JobAssignment_Go;
    1002 
    1003 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    1004   if (Loc>=0) and (Map[Loc] and fCity=0) and (Job=jNone)
    1005     and ((mix=mixSettlers) or (mix=mixSlaves))
    1006     and not JobAssignment_GotJob(uix) then
    1007     Unit_MoveEx(uix, maNextCity);
    1008 
    1009 //{$IFDEF DEBUG}DebugMessage(2, Format('Settler surplus in district 0: %d',[SettlerSurplus[0]]));{$ENDIF}
    1010 
    1011 // add settlers to city
    1012 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    1013   if (Loc>=0) and (Map[Loc] and fCity<>0)
    1014     and (MyModel[MyUnit[uix].mix].Kind=mkSettler) then
    1015     begin
    1016     dtr:=District[Loc];
    1017     if (mix<>mixSettlers)
    1018       or (dtr>=0) and (dtr<maxCOD)
    1019       and (SettlerSurplus[dtr]>DistrictPopulation[dtr] div 8) then
    1020       begin
    1021       City_FindMyCity(Loc, cix);
    1022       with MyCity[cix] do
    1023         if (Built[imSewer]>0)
    1024           or (Built[imAqueduct]>0) and (Size<=NeedSewerSize-2)
    1025           or (Size<=NeedAqueductSize-2) then
    1026           begin // settlers could be added to this city
    1027           Happy:=BasicHappy;
    1028           for i:=0 to 27 do if Built[i]>0 then inc(Happy);
    1029           if Built[imTemple]>0 then inc(Happy);
    1030           if Built[imCathedral]>0 then
    1031             begin
    1032             inc(Happy,2);
    1033             if RO.Wonder[woBach].EffectiveOwner=me then inc(Happy,1)
     1073          else
     1074            AddJob(Loc, jCity, 235);
     1075        end;
     1076        V21_to_Loc(Loc, Radius);
     1077        for V21 := 1 to 26 do
     1078        begin
     1079          Loc1 := Radius[V21];
     1080          if (Loc1 >= 0) and (RO.Map[Loc1] and (fTerrain or fSpecial) = fSwamp) then
     1081            AddJob(Loc1, jClear, 255);
     1082        end;
     1083      end;
     1084  end;
     1085
     1086  // choose all settlers to work
     1087  for uix := 0 to RO.nUn - 1 do
     1088    with MyUnit[uix] do
     1089      if (Loc >= 0) and ((mix = mixSettlers) or (mix = mixSlaves) or
     1090        (Data.BehaviorFlags and bBarbarina <> 0) and
     1091        (MyModel[mix].Kind = mkSettler)) then
     1092      begin
     1093        JobAssignment_AddUnit(uix);
     1094        if (District[Loc] >= 0) and (District[Loc] < maxCOD) then
     1095          Inc(SettlerSurplus[District[Loc]]);
     1096      end;
     1097
     1098  JobAssignment_Go;
     1099
     1100  for uix := 0 to RO.nUn - 1 do
     1101    with MyUnit[uix] do
     1102      if (Loc >= 0) and (Map[Loc] and fCity = 0) and (Job = jNone) and
     1103        ((mix = mixSettlers) or (mix = mixSlaves)) and not JobAssignment_GotJob(uix) then
     1104        Unit_MoveEx(uix, maNextCity);
     1105
     1106  //{$IFDEF DEBUG}DebugMessage(2, Format('Settler surplus in district 0: %d',[SettlerSurplus[0]]));{$ENDIF}
     1107
     1108  // add settlers to city
     1109  for uix := 0 to RO.nUn - 1 do
     1110    with MyUnit[uix] do
     1111      if (Loc >= 0) and (Map[Loc] and fCity <> 0) and
     1112        (MyModel[MyUnit[uix].mix].Kind = mkSettler) then
     1113      begin
     1114        dtr := District[Loc];
     1115        if (mix <> mixSettlers) or (dtr >= 0) and (dtr < maxCOD) and
     1116          (SettlerSurplus[dtr] > DistrictPopulation[dtr] div 8) then
     1117        begin
     1118          City_FindMyCity(Loc, cix);
     1119          with MyCity[cix] do
     1120            if (Built[imSewer] > 0) or (Built[imAqueduct] > 0) and
     1121              (Size <= NeedSewerSize - 2) or (Size <= NeedAqueductSize - 2) then
     1122            begin // settlers could be added to this city
     1123              Happy := BasicHappy;
     1124              for i := 0 to 27 do
     1125                if Built[i] > 0 then
     1126                  Inc(Happy);
     1127              if Built[imTemple] > 0 then
     1128                Inc(Happy);
     1129              if Built[imCathedral] > 0 then
     1130              begin
     1131                Inc(Happy, 2);
     1132                if RO.Wonder[woBach].EffectiveOwner = me then
     1133                  Inc(Happy, 1);
     1134              end;
     1135              if Built[imTheater] > 0 then
     1136                Inc(Happy, 2);
     1137              if (Built[imColosseum] > 0) or (Happy shl 1 >= Size + 2) then
     1138              begin // bigger city would be happy
     1139                //            {$IFDEF DEBUG}DebugMessage(2, Format('Adding settlers to city at %d',[Loc]));{$ENDIF}
     1140                Unit_AddToCity(uix);
     1141                if (dtr >= 0) and (dtr < maxCOD) then
     1142                  Dec(SettlerSurplus[dtr]);
     1143              end;
    10341144            end;
    1035           if Built[imTheater]>0 then inc(Happy,2);
    1036           if (Built[imColosseum]>0) or (Happy shl 1>=Size+2) then
    1037             begin // bigger city would be happy
    1038 //            {$IFDEF DEBUG}DebugMessage(2, Format('Adding settlers to city at %d',[Loc]));{$ENDIF}
    1039             Unit_AddToCity(uix);
    1040             if (dtr>=0) and (dtr<maxCOD) then dec(SettlerSurplus[dtr])
    1041             end
    1042           end;
    1043       end
    1044     end;
     1145        end;
     1146      end;
    10451147end; // ProcessSettlers
    10461148
     
    10521154procedure TAI.DoTurn;
    10531155var
    1054 emix,i,p1,TaxSum,ScienceSum,NewTaxRate: integer;
    1055 AllHateMe: boolean;
    1056 {$IFDEF PERF}PF,t0,t1,t2,t3,t4,t5,t6,t7,t8,t9: int64;{$ENDIF}
     1156  emix, i, p1, TaxSum, ScienceSum, NewTaxRate: integer;
     1157  AllHateMe: boolean;
     1158{$IFDEF PERF}
     1159  PF, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9: int64;
     1160{$ENDIF}
    10571161begin
    1058 {$IFDEF DEBUG}fillchar(DebugMap, sizeof(DebugMap),0);{$ENDIF}
    1059 
    1060 {$IFDEF PERF}QueryPerformanceFrequency(PF);{$ENDIF}
    1061 {$IFDEF PERF}QueryPerformanceCounter(t0);{$ENDIF}
    1062 
    1063 WarNations:=PresenceUnknown;
    1064 for p1:=0 to nPl-1 do
    1065   if (p1<>me) and (1 shl p1 and RO.Alive<>0) and (RO.Treaty[p1]<trPeace) then
    1066     inc(WarNations,1 shl p1);
    1067 BombardingNations:=0;
    1068 for emix:=0 to RO.nEnemyModel-1 do with RO.EnemyModel[emix] do
    1069   if (Domain=dSea) and (1 shl (mcLongRange-mcFirstNonCap) and Cap<>0) then
    1070     BombardingNations:=BombardingNations or (1 shl Owner);
    1071 BombardingNations:=BombardingNations and WarNations;
    1072 
    1073 AnalyzeMap;
    1074 //for i:=0 to MapSize-1 do DebugMap[i]:=Formation[i];
    1075 
    1076 if (Data.BehaviorFlags and bBarbarina=0)
    1077   and (RO.Tech[ResearchOrder[Data.BehaviorFlags and bGender,8]]<tsApplicable) then
    1078   CheckGender;
    1079 
    1080 if G.Difficulty[me]<MaxDiff then // not on beginner level
    1081   begin
    1082   if  (Data.LastResearchTech=adHorsebackRiding)
    1083     and (RO.ResearchTech<0) and (random(6)=0)
    1084     and (HavePort or (ContinentPresence[0] and not (1 shl me or PresenceUnknown)<>0)) then
    1085     begin
    1086     Data.BehaviorFlags:=Data.BehaviorFlags or bBarbarina_Hide;
    1087     DebugMessage(1, 'Early Barbarina!');
    1088     end;
    1089   if Data.BehaviorFlags and bBarbarina=0 then
    1090     begin
    1091     AllHateMe:=false;
    1092     for p1:=0 to nPl-1 do
    1093       if (1 shl p1 and RO.Alive<>0) and (RO.Treaty[p1]>=trNone) then
    1094         if (RO.Treaty[p1]<trPeace) and
    1095           ((Data.RejectTurn[suContact,p1]>=0)
    1096           or (Data.RejectTurn[suPeace,p1]>=0)) then
    1097           AllHateMe:=true
    1098         else begin AllHateMe:=false; break end;
    1099     if AllHateMe then
    1100       begin
    1101       Data.BehaviorFlags:=Data.BehaviorFlags or bBarbarina_Hide;
    1102       DebugMessage(1, 'All hate me!');
    1103       end
    1104     end;
    1105 
    1106   if Data.BehaviorFlags and bBarbarina=0 then
    1107     if Barbarina_GoHidden then
    1108       begin
    1109       Data.BehaviorFlags:=Data.BehaviorFlags or bBarbarina_Hide;
    1110       DebugMessage(1, 'Barbarina!');
    1111       end;
    1112   if Data.BehaviorFlags and bBarbarina=bBarbarina_Hide then
    1113     if Barbarina_Go then
    1114       begin
    1115       Data.BehaviorFlags:=Data.BehaviorFlags or bBarbarina;
    1116       DebugMessage(1, 'Barbarina - no mercy!');
    1117       end;
    1118   end;
    1119 
    1120 {$IFDEF PERF}QueryPerformanceCounter(t1);{$ENDIF}
     1162{$IFDEF DEBUG}
     1163  fillchar(DebugMap, sizeof(DebugMap), 0);
     1164{$ENDIF}
     1165
     1166{$IFDEF PERF}
     1167  QueryPerformanceFrequency(PF);
     1168{$ENDIF}
     1169{$IFDEF PERF}
     1170  QueryPerformanceCounter(t0);
     1171{$ENDIF}
     1172
     1173  WarNations := PresenceUnknown;
     1174  for p1 := 0 to nPl - 1 do
     1175    if (p1 <> me) and (1 shl p1 and RO.Alive <> 0) and (RO.Treaty[p1] < trPeace) then
     1176      Inc(WarNations, 1 shl p1);
     1177  BombardingNations := 0;
     1178  for emix := 0 to RO.nEnemyModel - 1 do
     1179    with RO.EnemyModel[emix] do
     1180      if (Domain = dSea) and (1 shl (mcLongRange - mcFirstNonCap) and Cap <> 0) then
     1181        BombardingNations := BombardingNations or (1 shl Owner);
     1182  BombardingNations := BombardingNations and WarNations;
     1183
     1184  AnalyzeMap;
     1185  //for i:=0 to MapSize-1 do DebugMap[i]:=Formation[i];
     1186
     1187  if (Data.BehaviorFlags and bBarbarina = 0) and
     1188    (RO.Tech[ResearchOrder[Data.BehaviorFlags and bGender, 8]] < tsApplicable) then
     1189    CheckGender;
     1190
     1191  if G.Difficulty[me] < MaxDiff then // not on beginner level
     1192  begin
     1193    if (Data.LastResearchTech = adHorsebackRiding) and (RO.ResearchTech < 0) and
     1194      (random(6) = 0) and (HavePort or (ContinentPresence[0] and not
     1195      (1 shl me or PresenceUnknown) <> 0)) then
     1196    begin
     1197      Data.BehaviorFlags := Data.BehaviorFlags or bBarbarina_Hide;
     1198      DebugMessage(1, 'Early Barbarina!');
     1199    end;
     1200    if Data.BehaviorFlags and bBarbarina = 0 then
     1201    begin
     1202      AllHateMe := False;
     1203      for p1 := 0 to nPl - 1 do
     1204        if (1 shl p1 and RO.Alive <> 0) and (RO.Treaty[p1] >= trNone) then
     1205          if (RO.Treaty[p1] < trPeace) and
     1206            ((Data.RejectTurn[suContact, p1] >= 0) or
     1207            (Data.RejectTurn[suPeace, p1] >= 0)) then
     1208            AllHateMe := True
     1209          else
     1210          begin
     1211            AllHateMe := False;
     1212            break;
     1213          end;
     1214      if AllHateMe then
     1215      begin
     1216        Data.BehaviorFlags := Data.BehaviorFlags or bBarbarina_Hide;
     1217        DebugMessage(1, 'All hate me!');
     1218      end;
     1219    end;
     1220
     1221    if Data.BehaviorFlags and bBarbarina = 0 then
     1222      if Barbarina_GoHidden then
     1223      begin
     1224        Data.BehaviorFlags := Data.BehaviorFlags or bBarbarina_Hide;
     1225        DebugMessage(1, 'Barbarina!');
     1226      end;
     1227    if Data.BehaviorFlags and bBarbarina = bBarbarina_Hide then
     1228      if Barbarina_Go then
     1229      begin
     1230        Data.BehaviorFlags := Data.BehaviorFlags or bBarbarina;
     1231        DebugMessage(1, 'Barbarina - no mercy!');
     1232      end;
     1233  end;
     1234
     1235{$IFDEF PERF}
     1236  QueryPerformanceCounter(t1);
     1237{$ENDIF}
    11211238
    11221239  // better government form available?
    1123 if (Data.BehaviorFlags and bBarbarina=0) and (RO.Turn>=LeaveDespotism)
    1124   and (RO.Government<>gAnarchy) then
    1125   if IsResearched(adDemocracy) then
    1126     begin
    1127     if RO.Government<>gDemocracy then
    1128       Revolution //!!!
     1240  if (Data.BehaviorFlags and bBarbarina = 0) and (RO.Turn >= LeaveDespotism) and
     1241    (RO.Government <> gAnarchy) then
     1242    if IsResearched(adDemocracy) then
     1243    begin
     1244      if RO.Government <> gDemocracy then
     1245        Revolution; //!!!
    11291246    end
    1130   else if IsResearched(adTheRepublic) then
    1131     begin
    1132     if RO.Government<>gRepublic then
    1133       Revolution
     1247    else if IsResearched(adTheRepublic) then
     1248    begin
     1249      if RO.Government <> gRepublic then
     1250        Revolution;
    11341251    end
    1135   else if IsResearched(adMonarchy) then
    1136     begin
    1137     if RO.Government<>gMonarchy then
    1138       Revolution
    1139     end;
    1140 
    1141 CollectModelCatStat;
    1142 
    1143 if Data.BehaviorFlags and bBarbarina=bBarbarina then
    1144   begin
    1145   MakeColonyShipPlan;
    1146   Barbarina_DoTurn
     1252    else if IsResearched(adMonarchy) then
     1253    begin
     1254      if RO.Government <> gMonarchy then
     1255        Revolution;
     1256    end;
     1257
     1258  CollectModelCatStat;
     1259
     1260  if Data.BehaviorFlags and bBarbarina = bBarbarina then
     1261  begin
     1262    MakeColonyShipPlan;
     1263    Barbarina_DoTurn;
    11471264  end
    1148 else
    1149   begin
    1150   {$IFDEF PERF}QueryPerformanceCounter(t2);{$ENDIF}
    1151 
    1152   {$IFDEF PERF}QueryPerformanceCounter(t3);{$ENDIF}
    1153 
    1154   AttackAndPatrol;
    1155 
    1156   {$IFDEF PERF}QueryPerformanceCounter(t4);{$ENDIF}
    1157 
    1158   MoveUnitsHome;
    1159 
    1160   {$IFDEF PERF}QueryPerformanceCounter(t5);{$ENDIF}
    1161   end;
    1162 
    1163 ProcessSettlers;
    1164 
    1165 {$IFDEF PERF}QueryPerformanceCounter(t6);{$ENDIF}
    1166 
    1167 if Data.BehaviorFlags and bBarbarina<>0 then
    1168   Barbarina_SetCityProduction
    1169 else
    1170   SetCityProduction;
    1171 
    1172 {$IFDEF PERF}QueryPerformanceCounter(t7);{$ENDIF}
    1173 
    1174 // correct tax rate if necessary
    1175 if not IsResearched(adWheel) then
    1176   ChangeRates(0,0)
    1177 else
    1178   begin
    1179   if (RO.TaxRate=0) or (RO.Money<(TotalPopulation[me]-4)*2) then
    1180     NewTaxRate:=RO.TaxRate // don't check decreasing tax
    1181   else NewTaxRate:=RO.TaxRate-10;
    1182   while NewTaxRate<100 do
    1183     begin
    1184     SumCities(NewTaxRate,TaxSum,ScienceSum);
    1185     if RO.Money+TaxSum>=(TotalPopulation[me]-4) then break; // enough
    1186     inc(NewTaxRate,10);
    1187     end;
    1188   if NewTaxRate<>RO.TaxRate then
    1189     begin
    1190   //  {$IFDEF DEBUG}DebugMessage(3,Format('New tax rate: %d',[NewTaxRate]));{$ENDIF}
    1191     ChangeRates(NewTaxRate,0)
    1192     end;
    1193   end;
    1194 
    1195 // clean up RequestedTechs
    1196 if (Data.LastResearchTech>=0)
    1197   and (Data.LastResearchTech<>RO.ResearchTech) then // research completed
    1198   for p1:=0 to nPl-1 do
    1199     if (p1<>me) and (1 shl p1 and RO.Alive<>0)
    1200       and (RO.EnemyReport[p1].TurnOfCivilReport+TechReportOutdated>RO.Turn)
    1201       and (RO.EnemyReport[p1].Tech[Data.LastResearchTech]<tsSeen) then
     1265  else
     1266  begin
     1267  {$IFDEF PERF}
     1268    QueryPerformanceCounter(t2);
     1269{$ENDIF}
     1270
     1271  {$IFDEF PERF}
     1272    QueryPerformanceCounter(t3);
     1273{$ENDIF}
     1274
     1275    AttackAndPatrol;
     1276
     1277  {$IFDEF PERF}
     1278    QueryPerformanceCounter(t4);
     1279{$ENDIF}
     1280
     1281    MoveUnitsHome;
     1282
     1283  {$IFDEF PERF}
     1284    QueryPerformanceCounter(t5);
     1285{$ENDIF}
     1286  end;
     1287
     1288  ProcessSettlers;
     1289
     1290{$IFDEF PERF}
     1291  QueryPerformanceCounter(t6);
     1292{$ENDIF}
     1293
     1294  if Data.BehaviorFlags and bBarbarina <> 0 then
     1295    Barbarina_SetCityProduction
     1296  else
     1297    SetCityProduction;
     1298
     1299{$IFDEF PERF}
     1300  QueryPerformanceCounter(t7);
     1301{$ENDIF}
     1302
     1303  // correct tax rate if necessary
     1304  if not IsResearched(adWheel) then
     1305    ChangeRates(0, 0)
     1306  else
     1307  begin
     1308    if (RO.TaxRate = 0) or (RO.Money < (TotalPopulation[me] - 4) * 2) then
     1309      NewTaxRate := RO.TaxRate // don't check decreasing tax
     1310    else
     1311      NewTaxRate := RO.TaxRate - 10;
     1312    while NewTaxRate < 100 do
     1313    begin
     1314      SumCities(NewTaxRate, TaxSum, ScienceSum);
     1315      if RO.Money + TaxSum >= (TotalPopulation[me] - 4) then
     1316        break; // enough
     1317      Inc(NewTaxRate, 10);
     1318    end;
     1319    if NewTaxRate <> RO.TaxRate then
     1320    begin
     1321      //  {$IFDEF DEBUG}DebugMessage(3,Format('New tax rate: %d',[NewTaxRate]));{$ENDIF}
     1322      ChangeRates(NewTaxRate, 0);
     1323    end;
     1324  end;
     1325
     1326  // clean up RequestedTechs
     1327  if (Data.LastResearchTech >= 0) and (Data.LastResearchTech <> RO.ResearchTech) then
     1328    // research completed
     1329    for p1 := 0 to nPl - 1 do
     1330      if (p1 <> me) and (1 shl p1 and RO.Alive <> 0) and
     1331        (RO.EnemyReport[p1].TurnOfCivilReport + TechReportOutdated > RO.Turn) and
     1332        (RO.EnemyReport[p1].Tech[Data.LastResearchTech] < tsSeen) then
    12021333      begin // latest researched advance might be of interest to this nation
    1203       for i:=0 to nRequestedTechs-1 do
    1204         if (Data.RequestedTechs[i]>=0)
    1205           and (Data.RequestedTechs[i] shr 8 and $F=p1) then
    1206           Data.RequestedTechs[i]:=-1;
    1207       end;
    1208 if RO.ResearchTech=adMilitary then Data.LastResearchTech:=-1
    1209 else Data.LastResearchTech:=RO.ResearchTech;
    1210 for i:=0 to nRequestedTechs-1 do
    1211   if (Data.RequestedTechs[i]>=0)
    1212     and (RO.Tech[Data.RequestedTechs[i] and $FF]>=tsSeen) then
    1213     Data.RequestedTechs[i]:=-1;
    1214 
    1215 // prepare negotiation
    1216 AdvanceValuesSet:=false;
    1217 SetAdvanceValues;
     1334        for i := 0 to nRequestedTechs - 1 do
     1335          if (Data.RequestedTechs[i] >= 0) and
     1336            (Data.RequestedTechs[i] shr 8 and $F = p1) then
     1337            Data.RequestedTechs[i] := -1;
     1338      end;
     1339  if RO.ResearchTech = adMilitary then
     1340    Data.LastResearchTech := -1
     1341  else
     1342    Data.LastResearchTech := RO.ResearchTech;
     1343  for i := 0 to nRequestedTechs - 1 do
     1344    if (Data.RequestedTechs[i] >= 0) and
     1345      (RO.Tech[Data.RequestedTechs[i] and $FF] >= tsSeen) then
     1346      Data.RequestedTechs[i] := -1;
     1347
     1348  // prepare negotiation
     1349  AdvanceValuesSet := False;
     1350  SetAdvanceValues;
    12181351
    12191352
     
    12251358{$ENDIF}
    12261359
    1227 {$IFDEF PERF}DebugMessage(2,Format('t1=%d t2=%d t3=%d t4=%d t5=%d t6=%d t7=%d t8=%d t9=%d (ns)',[(t1-t0)*1000000 div PF,(t2-t1)*1000000 div PF,(t3-t2)*1000000 div PF,(t4-t3)*1000000 div PF,(t5-t4)*1000000 div PF,(t6-t5)*1000000 div PF,(t7-t6)*1000000 div PF,(t8-t7)*1000000 div PF,(t9-t8)*1000000 div PF]));{$ENDIF}
     1360{$IFDEF PERF}
     1361  DebugMessage(2, Format('t1=%d t2=%d t3=%d t4=%d t5=%d t6=%d t7=%d t8=%d t9=%d (ns)',
     1362    [(t1 - t0) * 1000000 div PF, (t2 - t1) * 1000000 div PF, (t3 - t2) *
     1363    1000000 div PF, (t4 - t3) * 1000000 div PF, (t5 - t4) * 1000000 div PF,
     1364    (t6 - t5) * 1000000 div PF, (t7 - t6) * 1000000 div PF, (t8 - t7) *
     1365    1000000 div PF, (t9 - t8) * 1000000 div PF]));
     1366{$ENDIF}
    12281367end;
    12291368
     
    12311370procedure TAI.TraceAdvanceValues(Nation: integer);
    12321371var
    1233 ad: integer;
     1372  ad: integer;
    12341373begin
    1235 for ad:=0 to nAdv-1 do
    1236   if (RO.Tech[ad]<tsSeen) and (RO.EnemyReport[Nation].Tech[ad]>=tsApplicable)
    1237     and (AdvanceValue[ad]>0) then
    1238     begin
    1239     DebugMessage(2,Format('%s (%d): +%x',
    1240       [Name_Advance[ad], Advancedness[ad], AdvanceValue[ad]]))
    1241     end
     1374  for ad := 0 to nAdv - 1 do
     1375    if (RO.Tech[ad] < tsSeen) and (RO.EnemyReport[Nation].Tech[ad] >= tsApplicable) and
     1376      (AdvanceValue[ad] > 0) then
     1377    begin
     1378      DebugMessage(2, Format('%s (%d): +%x', [Name_Advance[ad],
     1379        Advancedness[ad], AdvanceValue[ad]]));
     1380    end;
    12421381end;
     1382
    12431383{$ENDIF}
    12441384
     
    12461386procedure TAI.CheckGender;
    12471387var
    1248 p1,NewGender: integer;
     1388  p1, NewGender: integer;
    12491389begin
    1250 NewGender:=-1;
    1251 for p1:=0 to nPl-1 do
    1252   if (p1<>me) and (1 shl p1 and RO.Alive<>0)
    1253     and (RO.Treaty[p1]>=trFriendlyContact) then
    1254     if PlayerHash[me]>PlayerHash[p1] then
    1255       begin
    1256       if NewGender=bMale then
    1257         begin NewGender:=-2; break end; // ambiguous, don't change gender
    1258       NewGender:=bFemale;
     1390  NewGender := -1;
     1391  for p1 := 0 to nPl - 1 do
     1392    if (p1 <> me) and (1 shl p1 and RO.Alive <> 0) and
     1393      (RO.Treaty[p1] >= trFriendlyContact) then
     1394      if PlayerHash[me] > PlayerHash[p1] then
     1395      begin
     1396        if NewGender = bMale then
     1397        begin
     1398          NewGender := -2;
     1399          break;
     1400        end; // ambiguous, don't change gender
     1401        NewGender := bFemale;
    12591402      end
    1260     else
    1261       begin
    1262       if NewGender=bFemale then
    1263         begin NewGender:=-2; break end; // ambiguous, don't change gender
    1264       NewGender:=bMale;
    1265       end;
    1266 if (NewGender>=0) and (NewGender<>Data.BehaviorFlags and bGender) then
    1267   begin
    1268   Data.BehaviorFlags:=Data.BehaviorFlags and not bGender or NewGender;
    1269   DebugMessage(1, 'Gender:='+char(48+NewGender));
    1270   end
     1403      else
     1404      begin
     1405        if NewGender = bFemale then
     1406        begin
     1407          NewGender := -2;
     1408          break;
     1409        end; // ambiguous, don't change gender
     1410        NewGender := bMale;
     1411      end;
     1412  if (NewGender >= 0) and (NewGender <> Data.BehaviorFlags and bGender) then
     1413  begin
     1414    Data.BehaviorFlags := Data.BehaviorFlags and not bGender or NewGender;
     1415    DebugMessage(1, 'Gender:=' + char(48 + NewGender));
     1416  end;
    12711417end;
    12721418
     
    12761422  procedure RateResearchAdv(ad, Time: integer);
    12771423  var
    1278   Value: integer;
    1279   begin
    1280   if Time=0 then Value:=TechValue_ForResearch_Next
    1281   else Value:=TechValue_ForResearch-Time;
    1282   if AdvanceValue[ad]<Value then
    1283     AdvanceValue[ad]:=Value;
     1424    Value: integer;
     1425  begin
     1426    if Time = 0 then
     1427      Value := TechValue_ForResearch_Next
     1428    else
     1429      Value := TechValue_ForResearch - Time;
     1430    if AdvanceValue[ad] < Value then
     1431      AdvanceValue[ad] := Value;
    12841432  end;
    12851433
    12861434  procedure SetPreqValues(ad, Value: integer);
    12871435  begin
    1288   if (RO.Tech[ad]<tsSeen) and (ad<>RO.ResearchTech) then
    1289     begin
    1290     if AdvanceValue[ad]<Value then
    1291       AdvanceValue[ad]:=Value;
    1292     if ad=adScience then
    1293       begin
    1294       SetPreqValues(adTheology,Value-1);
    1295       SetPreqValues(adPhilosophy,Value-1);
     1436    if (RO.Tech[ad] < tsSeen) and (ad <> RO.ResearchTech) then
     1437    begin
     1438      if AdvanceValue[ad] < Value then
     1439        AdvanceValue[ad] := Value;
     1440      if ad = adScience then
     1441      begin
     1442        SetPreqValues(adTheology, Value - 1);
     1443        SetPreqValues(adPhilosophy, Value - 1);
    12961444      end
    1297     else if ad=adMassProduction then
     1445      else if ad = adMassProduction then
    12981446      // preqs should be researched now
    1299     else
    1300       begin
    1301       if AdvPreq[ad,0]>=0 then
    1302         SetPreqValues(AdvPreq[ad,0],Value-1);
    1303       if AdvPreq[ad,1]>=0 then
    1304         SetPreqValues(AdvPreq[ad,1],Value-1);
    1305       end;
    1306     end
     1447      else
     1448      begin
     1449        if AdvPreq[ad, 0] >= 0 then
     1450          SetPreqValues(AdvPreq[ad, 0], Value - 1);
     1451        if AdvPreq[ad, 1] >= 0 then
     1452          SetPreqValues(AdvPreq[ad, 1], Value - 1);
     1453      end;
     1454    end;
    13071455  end;
    13081456
    13091457  procedure RateImpPreq(iix, Value: integer);
    13101458  begin
    1311   if (Value>0) and (Imp[iix].Preq>=0) then
    1312     inc(AdvanceValue[Imp[iix].Preq],Value);
     1459    if (Value > 0) and (Imp[iix].Preq >= 0) then
     1460      Inc(AdvanceValue[Imp[iix].Preq], Value);
    13131461  end;
    13141462
    13151463var
    1316 emix,cix,adMissing,iad,ad,count,i,Time,d,CurrentCost,CurrentStrength,
    1317   MaxSize, MaxTrade: integer;
    1318 PreView,Emergency,Bombarded: boolean;
     1464  emix, cix, adMissing, iad, ad, Count, i, Time, d, CurrentCost,
     1465  CurrentStrength, MaxSize, MaxTrade: integer;
     1466  PreView, Emergency, Bombarded: boolean;
    13191467begin
    1320 if AdvanceValuesSet then exit;
    1321 AdvanceValuesSet:=true;
    1322 
    1323 fillchar(AdvanceValue,sizeof(AdvanceValue),0);
    1324 
    1325 // rate techs to ensure research progress
    1326 Time:=0;
    1327 for ad:=0 to nAdv-1 do if RO.Tech[ad]=tsSeen then inc(Time);
    1328 adMissing:=-1;
    1329 Emergency:=true;
    1330 for iad:=0 to nResearchOrder-1 do
    1331   begin
    1332   ad:=ResearchOrder[Data.BehaviorFlags and bGender,iad];
    1333   if (ad<>RO.ResearchTech) and (RO.Tech[ad]<tsSeen) then
    1334     begin
    1335     if adMissing<0 then adMissing:=ad;
    1336     RateResearchAdv(ad,Time); // unseen tech of own gender
    1337     if AdvPreq[ad,2]<>preNone then
     1468  if AdvanceValuesSet then
     1469    exit;
     1470  AdvanceValuesSet := True;
     1471
     1472  fillchar(AdvanceValue, sizeof(AdvanceValue), 0);
     1473
     1474  // rate techs to ensure research progress
     1475  Time := 0;
     1476  for ad := 0 to nAdv - 1 do
     1477    if RO.Tech[ad] = tsSeen then
     1478      Inc(Time);
     1479  adMissing := -1;
     1480  Emergency := True;
     1481  for iad := 0 to nResearchOrder - 1 do
     1482  begin
     1483    ad := ResearchOrder[Data.BehaviorFlags and bGender, iad];
     1484    if (ad <> RO.ResearchTech) and (RO.Tech[ad] < tsSeen) then
     1485    begin
     1486      if adMissing < 0 then
     1487        adMissing := ad;
     1488      RateResearchAdv(ad, Time); // unseen tech of own gender
     1489      if AdvPreq[ad, 2] <> preNone then
    13381490      begin // 2 of 3 required
    1339       count:=0;
    1340       for i:=0 to 2 do
    1341         if (AdvPreq[ad,i]=RO.ResearchTech)
    1342           or (RO.Tech[AdvPreq[ad,i]]>=tsSeen) then
    1343           inc(count);
    1344       if count>=2 then Emergency:=false
     1491        Count := 0;
     1492        for i := 0 to 2 do
     1493          if (AdvPreq[ad, i] = RO.ResearchTech) or
     1494            (RO.Tech[AdvPreq[ad, i]] >= tsSeen) then
     1495            Inc(Count);
     1496        if Count >= 2 then
     1497          Emergency := False
     1498        else
     1499        begin
     1500          if ad <> adMassProduction then // don't score third preq for MP
     1501          begin
     1502            for i := 0 to 2 do
     1503              if (AdvPreq[ad, i] <> RO.ResearchTech) and
     1504                (RO.Tech[AdvPreq[ad, i]] < tsSeen) then
     1505                RateResearchAdv(AdvPreq[ad, i], Time);
     1506          end;
     1507          Inc(Time, 2 - Count);
     1508        end;
     1509      end
    13451510      else
    1346         begin
    1347         if ad<>adMassProduction then // don't score third preq for MP
     1511      begin
     1512        Count := 0;
     1513        for i := 0 to 1 do
     1514          if (AdvPreq[ad, i] <> preNone) and (AdvPreq[ad, i] <> RO.ResearchTech) and
     1515            (RO.Tech[AdvPreq[ad, i]] < tsSeen) then
    13481516          begin
    1349           for i:=0 to 2 do
    1350             if (AdvPreq[ad,i]<>RO.ResearchTech)
    1351               and (RO.Tech[AdvPreq[ad,i]]<tsSeen) then
    1352               RateResearchAdv(AdvPreq[ad,i],Time);
     1517            RateResearchAdv(AdvPreq[ad, i], Time);
     1518            Inc(Count);
    13531519          end;
    1354         inc(Time,2-count)
    1355         end
    1356       end
    1357     else
    1358       begin
    1359       count:=0;
    1360       for i:=0 to 1 do
    1361         if (AdvPreq[ad,i]<>preNone) and (AdvPreq[ad,i]<>RO.ResearchTech)
    1362           and (RO.Tech[AdvPreq[ad,i]]<tsSeen) then
    1363           begin
    1364           RateResearchAdv(AdvPreq[ad,i],Time);
    1365           inc(count)
    1366           end;
    1367       if count=0 then Emergency:=false;
    1368       inc(Time,count);
    1369       end;
    1370     inc(Time,2);
    1371     end
    1372   end;
    1373 if Emergency and (adMissing>=0) then
    1374   begin
    1375   {$IFDEF DEBUG}DebugMessage(2, 'Research emergency: Go for'
    1376     +Name_Advance[adMissing]+' now!');{$ENDIF}
    1377   SetPreqValues(adMissing, TechValue_ForResearch_Urgent);
    1378   end;
    1379 for iad:=0 to nResearchOrder-1 do
    1380   begin
    1381   ad:=ResearchOrder[Data.BehaviorFlags and bGender xor 1,iad];
    1382   if ad=adScience then
    1383     inc(AdvanceValue[ad], 5*TechValue_ForResearch_LeaveOut)
    1384   else if LeaveOutValue[ad]>0 then
    1385     if AdvanceValue[ad]>0 then
    1386       inc(AdvanceValue[ad], LeaveOutValue[ad]*TechValue_ForResearch_LeaveOut)
    1387 //    else AdvanceValue[ad]:=1;
    1388   end;
    1389 
    1390 // rate military techs
    1391 for d:=0 to nDomains-1 do
    1392   begin
    1393   CurrentCost:=0;
    1394   CurrentStrength:=0;
    1395   for PreView:=true downto false do
    1396     for i:=0 to nUpgrade-1 do with Upgrade[d,i] do
    1397       if (Preq>=0) and not (Preq in FutureTech) then
    1398         if ((Ro.ResearchTech=Preq) or (RO.Tech[Preq]>=tsSeen)) = PreView then
    1399           if PreView then
    1400             begin
    1401             if Cost>CurrentCost then CurrentCost:=Cost;
    1402             inc(CurrentStrength, Strength);
    1403             end
    1404           else
    1405             begin // rate
    1406             if (i>0) and (Trans>0) then inc(AdvanceValue[Preq],$400);
    1407             if Cost<=CurrentCost then
    1408               inc(AdvanceValue[Preq], (4-d)*Strength*$400 div (CurrentStrength+Upgrade[d,0].Strength))
    1409             else inc(AdvanceValue[Preq], (4-d)*Strength*$200 div (CurrentStrength+Upgrade[d,0].Strength))
    1410             end;
    1411   end;
    1412 // speed
    1413 inc(AdvanceValue[adSteamEngine],$400);
    1414 inc(AdvanceValue[adNuclearPower],$400);
    1415 inc(AdvanceValue[adRocketry],$400);
    1416 // features
    1417 inc(AdvanceValue[adBallistics],$800);
    1418 inc(AdvanceValue[adCommunism],$800);
    1419 // weight
    1420 inc(AdvanceValue[adAutomobile],$800);
    1421 inc(AdvanceValue[adSteel],$800);
    1422 inc(AdvanceValue[adAdvancedFlight],$400);
    1423 
    1424 // civil non-improvement
    1425 if RO.Turn>=LeaveDespotism then
    1426   begin
    1427   inc(AdvanceValue[adDemocracy],$80*RO.nCity);
    1428   inc(AdvanceValue[adTheRepublic],$800);
    1429   end;
    1430 inc(AdvanceValue[adRailroad],$800);
    1431 // inc(AdvanceValue[adExplosives],$800); // no, has enough
    1432 inc(AdvanceValue[adBridgeBuilding],$200);
    1433 inc(AdvanceValue[adSpaceFlight],$200);
    1434 inc(AdvanceValue[adSelfContainedEnvironment],$200);
    1435 inc(AdvanceValue[adImpulseDrive],$200);
    1436 inc(AdvanceValue[adTransstellarColonization],$200);
    1437 
    1438 // city improvements
    1439 MaxSize:=0;
    1440 for cix:=0 to RO.nCity-1 do
    1441   if MyCity[cix].Size>MaxSize then
    1442     MaxSize:=MyCity[cix].Size;
    1443 if RO.Government in [gRepublic,gDemocracy,gLybertarianism] then
    1444   MaxTrade:=(MaxSize-1)*3
    1445 else MaxTrade:=(MaxSize-1)*2;
    1446 
    1447 RateImpPreq(imCourt,(RO.nCity-1)*$100);
    1448 RateImpPreq(imLibrary,(MaxTrade-10)*$180);
    1449 RateImpPreq(imMarket,(MaxTrade-10)*$140);
    1450 RateImpPreq(imUniversity,(MaxTrade-10)*$140);
    1451 RateImpPreq(imBank,(MaxTrade-10)*$100);
    1452 RateImpPreq(imObservatory,(MaxTrade-10)*$100);
    1453 RateImpPreq(imResLab,(MaxTrade-14)*$140);
    1454 RateImpPreq(imStockEx,(MaxTrade-10)*$10*(RO.nCity-1));
    1455 RateImpPreq(imHighways,(MaxSize-5)*$200);
    1456 RateImpPreq(imFactory,(MaxSize-8)*$200);
    1457 RateImpPreq(imMfgPlant,(MaxSize-8)*$1C0);
    1458 RateImpPreq(imRecycling,(MaxSize-8)*$180);
    1459 RateImpPreq(imHarbor,(MaxSize-7)*$200);
    1460 RateImpPreq(imSuperMarket,$300);
    1461 if RO.Turn>=40 then RateImpPreq(imTemple,$400);
    1462 if RO.Government<>gDespotism then
    1463   begin
    1464   RateImpPreq(imCathedral,$400);
    1465   RateImpPreq(imTheater,$400);
    1466   end;
    1467 if MaxSize>=NeedAqueductSize-1 then
    1468   begin
    1469   RateImpPreq(imAqueduct,$600);
    1470   RateImpPreq(imGrWall,$300);
    1471   end;
    1472 if cixStateImp[imPalace]>=0 then
    1473   with MyCity[cixStateImp[imPalace]] do
    1474     if (Built[imColosseum]+Built[imObservatory]>0) and (Size>=NeedSewerSize-1) then
    1475       RateImpPreq(imSewer,$400);
    1476 Bombarded:=false;
    1477 for emix:=0 to RO.nEnemyModel-1 do
    1478   if 1 shl (mcLongRange-mcFirstNonCap) and RO.EnemyModel[emix].Cap<>0 then
    1479     Bombarded:=true;
    1480 if Bombarded then
    1481   RateImpPreq(imCoastalFort,$400);
     1520        if Count = 0 then
     1521          Emergency := False;
     1522        Inc(Time, Count);
     1523      end;
     1524      Inc(Time, 2);
     1525    end;
     1526  end;
     1527  if Emergency and (adMissing >= 0) then
     1528  begin
     1529  {$IFDEF DEBUG}
     1530    DebugMessage(2, 'Research emergency: Go for' + Name_Advance[adMissing] + ' now!');
     1531{$ENDIF}
     1532    SetPreqValues(adMissing, TechValue_ForResearch_Urgent);
     1533  end;
     1534  for iad := 0 to nResearchOrder - 1 do
     1535  begin
     1536    ad := ResearchOrder[Data.BehaviorFlags and bGender xor 1, iad];
     1537    if ad = adScience then
     1538      Inc(AdvanceValue[ad], 5 * TechValue_ForResearch_LeaveOut)
     1539    else if LeaveOutValue[ad] > 0 then
     1540      if AdvanceValue[ad] > 0 then
     1541        Inc(AdvanceValue[ad], LeaveOutValue[ad] * TechValue_ForResearch_LeaveOut);
     1542    //    else AdvanceValue[ad]:=1;
     1543  end;
     1544
     1545  // rate military techs
     1546  for d := 0 to nDomains - 1 do
     1547  begin
     1548    CurrentCost := 0;
     1549    CurrentStrength := 0;
     1550    for PreView := True downto False do
     1551      for i := 0 to nUpgrade - 1 do
     1552        with Upgrade[d, i] do
     1553          if (Preq >= 0) and not (Preq in FutureTech) then
     1554            if ((Ro.ResearchTech = Preq) or (RO.Tech[Preq] >= tsSeen)) = PreView then
     1555              if PreView then
     1556              begin
     1557                if Cost > CurrentCost then
     1558                  CurrentCost := Cost;
     1559                Inc(CurrentStrength, Strength);
     1560              end
     1561              else
     1562              begin // rate
     1563                if (i > 0) and (Trans > 0) then
     1564                  Inc(AdvanceValue[Preq], $400);
     1565                if Cost <= CurrentCost then
     1566                  Inc(AdvanceValue[Preq], (4 - d) * Strength * $400 div
     1567                    (CurrentStrength + Upgrade[d, 0].Strength))
     1568                else
     1569                  Inc(AdvanceValue[Preq], (4 - d) * Strength * $200 div
     1570                    (CurrentStrength + Upgrade[d, 0].Strength));
     1571              end;
     1572  end;
     1573  // speed
     1574  Inc(AdvanceValue[adSteamEngine], $400);
     1575  Inc(AdvanceValue[adNuclearPower], $400);
     1576  Inc(AdvanceValue[adRocketry], $400);
     1577  // features
     1578  Inc(AdvanceValue[adBallistics], $800);
     1579  Inc(AdvanceValue[adCommunism], $800);
     1580  // weight
     1581  Inc(AdvanceValue[adAutomobile], $800);
     1582  Inc(AdvanceValue[adSteel], $800);
     1583  Inc(AdvanceValue[adAdvancedFlight], $400);
     1584
     1585  // civil non-improvement
     1586  if RO.Turn >= LeaveDespotism then
     1587  begin
     1588    Inc(AdvanceValue[adDemocracy], $80 * RO.nCity);
     1589    Inc(AdvanceValue[adTheRepublic], $800);
     1590  end;
     1591  Inc(AdvanceValue[adRailroad], $800);
     1592  // inc(AdvanceValue[adExplosives],$800); // no, has enough
     1593  Inc(AdvanceValue[adBridgeBuilding], $200);
     1594  Inc(AdvanceValue[adSpaceFlight], $200);
     1595  Inc(AdvanceValue[adSelfContainedEnvironment], $200);
     1596  Inc(AdvanceValue[adImpulseDrive], $200);
     1597  Inc(AdvanceValue[adTransstellarColonization], $200);
     1598
     1599  // city improvements
     1600  MaxSize := 0;
     1601  for cix := 0 to RO.nCity - 1 do
     1602    if MyCity[cix].Size > MaxSize then
     1603      MaxSize := MyCity[cix].Size;
     1604  if RO.Government in [gRepublic, gDemocracy, gLybertarianism] then
     1605    MaxTrade := (MaxSize - 1) * 3
     1606  else
     1607    MaxTrade := (MaxSize - 1) * 2;
     1608
     1609  RateImpPreq(imCourt, (RO.nCity - 1) * $100);
     1610  RateImpPreq(imLibrary, (MaxTrade - 10) * $180);
     1611  RateImpPreq(imMarket, (MaxTrade - 10) * $140);
     1612  RateImpPreq(imUniversity, (MaxTrade - 10) * $140);
     1613  RateImpPreq(imBank, (MaxTrade - 10) * $100);
     1614  RateImpPreq(imObservatory, (MaxTrade - 10) * $100);
     1615  RateImpPreq(imResLab, (MaxTrade - 14) * $140);
     1616  RateImpPreq(imStockEx, (MaxTrade - 10) * $10 * (RO.nCity - 1));
     1617  RateImpPreq(imHighways, (MaxSize - 5) * $200);
     1618  RateImpPreq(imFactory, (MaxSize - 8) * $200);
     1619  RateImpPreq(imMfgPlant, (MaxSize - 8) * $1C0);
     1620  RateImpPreq(imRecycling, (MaxSize - 8) * $180);
     1621  RateImpPreq(imHarbor, (MaxSize - 7) * $200);
     1622  RateImpPreq(imSuperMarket, $300);
     1623  if RO.Turn >= 40 then
     1624    RateImpPreq(imTemple, $400);
     1625  if RO.Government <> gDespotism then
     1626  begin
     1627    RateImpPreq(imCathedral, $400);
     1628    RateImpPreq(imTheater, $400);
     1629  end;
     1630  if MaxSize >= NeedAqueductSize - 1 then
     1631  begin
     1632    RateImpPreq(imAqueduct, $600);
     1633    RateImpPreq(imGrWall, $300);
     1634  end;
     1635  if cixStateImp[imPalace] >= 0 then
     1636    with MyCity[cixStateImp[imPalace]] do
     1637      if (Built[imColosseum] + Built[imObservatory] > 0) and
     1638        (Size >= NeedSewerSize - 1) then
     1639        RateImpPreq(imSewer, $400);
     1640  Bombarded := False;
     1641  for emix := 0 to RO.nEnemyModel - 1 do
     1642    if 1 shl (mcLongRange - mcFirstNonCap) and RO.EnemyModel[emix].Cap <> 0 then
     1643      Bombarded := True;
     1644  if Bombarded then
     1645    RateImpPreq(imCoastalFort, $400);
    14821646end;
    14831647
    14841648procedure TAI.AnalyzeMap;
    14851649var
    1486 cix,Loc,Loc1,V8,f1,p1: integer;
    1487 Adjacent: TVicinity8Loc;
     1650  cix, Loc, Loc1, V8, f1, p1: integer;
     1651  Adjacent: TVicinity8Loc;
    14881652begin
    1489 inherited AnalyzeMap;
    1490 
    1491 // collect nation presence information for continents and oceans
    1492 fillchar(ContinentPresence, sizeof(ContinentPresence), 0);
    1493 fillchar(OceanPresence, sizeof(OceanPresence), 0);
    1494 for Loc:=0 to MapSize-1 do
    1495   begin
    1496   f1:=Formation[Loc];
    1497   case f1 of
    1498     0..maxCOD-1:
    1499       begin
    1500       p1:=RO.Territory[Loc];
    1501       if p1>=0 then
    1502         if Map[Loc] and fTerrain>=fGrass then
    1503           ContinentPresence[f1]:=ContinentPresence[f1] or (1 shl p1)
    1504         else OceanPresence[f1]:=OceanPresence[f1] or (1 shl p1);
    1505       end;
    1506     nfUndiscovered:
     1653  inherited;
     1654
     1655  // collect nation presence information for continents and oceans
     1656  fillchar(ContinentPresence, sizeof(ContinentPresence), 0);
     1657  fillchar(OceanPresence, sizeof(OceanPresence), 0);
     1658  for Loc := 0 to MapSize - 1 do
     1659  begin
     1660    f1 := Formation[Loc];
     1661    case f1 of
     1662      0..maxCOD - 1:
     1663      begin
     1664        p1 := RO.Territory[Loc];
     1665        if p1 >= 0 then
     1666          if Map[Loc] and fTerrain >= fGrass then
     1667            ContinentPresence[f1] := ContinentPresence[f1] or (1 shl p1)
     1668          else
     1669            OceanPresence[f1] := OceanPresence[f1] or (1 shl p1);
     1670      end;
     1671      nfUndiscovered:
    15071672      begin // adjacent formations are not completely discovered
    1508       V8_to_Loc(Loc,Adjacent);
    1509       for V8:=0 to 7 do
    1510         begin
    1511         Loc1:=Adjacent[V8];
    1512         if Loc1>=0 then
     1673        V8_to_Loc(Loc, Adjacent);
     1674        for V8 := 0 to 7 do
     1675        begin
     1676          Loc1 := Adjacent[V8];
     1677          if Loc1 >= 0 then
    15131678          begin
    1514           f1:=Formation[Loc1];
    1515           if (f1>=0) and (f1<maxCOD) then
    1516             if Map[Loc1] and fTerrain>=fGrass then
    1517               ContinentPresence[f1]:=ContinentPresence[f1] or PresenceUnknown
    1518             else OceanPresence[f1]:=OceanPresence[f1] or PresenceUnknown
    1519           end
    1520         end
    1521       end;
    1522     nfPeace:
     1679            f1 := Formation[Loc1];
     1680            if (f1 >= 0) and (f1 < maxCOD) then
     1681              if Map[Loc1] and fTerrain >= fGrass then
     1682                ContinentPresence[f1] := ContinentPresence[f1] or PresenceUnknown
     1683              else
     1684                OceanPresence[f1] := OceanPresence[f1] or PresenceUnknown;
     1685          end;
     1686        end;
     1687      end;
     1688      nfPeace:
    15231689      begin // nation present in adjacent formations
    1524       V8_to_Loc(Loc,Adjacent);
    1525       for V8:=0 to 7 do
    1526         begin
    1527         Loc1:=Adjacent[V8];
    1528         if Loc1>=0 then
     1690        V8_to_Loc(Loc, Adjacent);
     1691        for V8 := 0 to 7 do
     1692        begin
     1693          Loc1 := Adjacent[V8];
     1694          if Loc1 >= 0 then
    15291695          begin
    1530           f1:=Formation[Loc1];
    1531           if (f1>=0) and (f1<maxCOD) then
    1532             if Map[Loc1] and fTerrain>=fGrass then
    1533               ContinentPresence[f1]:=ContinentPresence[f1]
    1534                 or (1 shl RO.Territory[Loc])
    1535             else OceanPresence[f1]:=OceanPresence[f1]
    1536               or (1 shl RO.Territory[Loc])
    1537           end
    1538         end
    1539       end;
    1540     end;
    1541   end;
    1542 
    1543 fillchar(TotalPopulation, sizeof(TotalPopulation), 0);
    1544 fillchar(ContinentPopulation, sizeof(ContinentPopulation), 0);
    1545 fillchar(DistrictPopulation, 4*nDistrict, 0);
    1546 
    1547 // count population
    1548 for cix:=0 to RO.nEnemyCity-1 do with RO.EnemyCity[cix] do if Loc>=0 then
    1549   begin
    1550   inc(TotalPopulation[Owner],Size);
    1551   if (Formation[Loc]>=0) and (Formation[Loc]<maxCOD) then
    1552     inc(ContinentPopulation[Owner,Formation[Loc]],Size);
    1553   end;
    1554 for cix:=0 to RO.nCity-1 do with RO.City[cix] do if Loc>=0 then
    1555   begin
    1556   inc(TotalPopulation[me],Size);
    1557   assert(District[Loc]>=0);
    1558   if District[Loc]<maxCOD then
    1559     inc(DistrictPopulation[District[Loc]],Size);
    1560   end;
     1696            f1 := Formation[Loc1];
     1697            if (f1 >= 0) and (f1 < maxCOD) then
     1698              if Map[Loc1] and fTerrain >= fGrass then
     1699                ContinentPresence[f1] :=
     1700                  ContinentPresence[f1] or (1 shl RO.Territory[Loc])
     1701              else
     1702                OceanPresence[f1] := OceanPresence[f1] or (1 shl RO.Territory[Loc]);
     1703          end;
     1704        end;
     1705      end;
     1706    end;
     1707  end;
     1708
     1709  fillchar(TotalPopulation, sizeof(TotalPopulation), 0);
     1710  fillchar(ContinentPopulation, sizeof(ContinentPopulation), 0);
     1711  fillchar(DistrictPopulation, 4 * nDistrict, 0);
     1712
     1713  // count population
     1714  for cix := 0 to RO.nEnemyCity - 1 do
     1715    with RO.EnemyCity[cix] do
     1716      if Loc >= 0 then
     1717      begin
     1718        Inc(TotalPopulation[Owner], Size);
     1719        if (Formation[Loc] >= 0) and (Formation[Loc] < maxCOD) then
     1720          Inc(ContinentPopulation[Owner, Formation[Loc]], Size);
     1721      end;
     1722  for cix := 0 to RO.nCity - 1 do
     1723    with RO.City[cix] do
     1724      if Loc >= 0 then
     1725      begin
     1726        Inc(TotalPopulation[me], Size);
     1727        assert(District[Loc] >= 0);
     1728        if District[Loc] < maxCOD then
     1729          Inc(DistrictPopulation[District[Loc]], Size);
     1730      end;
    15611731end;
    15621732
    15631733procedure TAI.CollectModelCatStat;
    15641734var
    1565 i,uix,Cat,mix,Quality: integer;
     1735  i, uix, Cat, mix, Quality: integer;
    15661736begin
    1567 // categorize models
    1568 for Cat:=0 to nModelCat-1 do
    1569   ModelBestQuality[Cat]:=0;
    1570 mixCaravan:=-1;
    1571 mixSlaves:=-1;
    1572 mixCruiser:=-1;
    1573 for mix:=0 to RO.nModel-1 do
    1574   begin
    1575   ModelCat[mix]:=mctNone;
    1576   if mix=1 then mixMilitia:=mix
    1577   else
    1578     case MyModel[mix].Kind of
    1579       $00..$0F: // common units
    1580         if MyModel[mix].Cap[mcNav]>0 then mixCruiser:=mix // temporary!!!
    1581         else
     1737  // categorize models
     1738  for Cat := 0 to nModelCat - 1 do
     1739    ModelBestQuality[Cat] := 0;
     1740  mixCaravan := -1;
     1741  mixSlaves := -1;
     1742  mixCruiser := -1;
     1743  for mix := 0 to RO.nModel - 1 do
     1744  begin
     1745    ModelCat[mix] := mctNone;
     1746    if mix = 1 then
     1747      mixMilitia := mix
     1748    else
     1749      case MyModel[mix].Kind of
     1750        $00..$0F: // common units
     1751          if MyModel[mix].Cap[mcNav] > 0 then
     1752            mixCruiser := mix // temporary!!!
     1753          else
    15821754          begin
    1583           RateMyModel(mix,Cat,Quality);
    1584           ModelCat[mix]:=Cat;
    1585           ModelQuality[mix]:=Quality;
    1586           if (Cat>=0) and (Quality>ModelBestQuality[Cat]) then
    1587             ModelBestQuality[Cat]:=Quality;
     1755            RateMyModel(mix, Cat, Quality);
     1756            ModelCat[mix] := Cat;
     1757            ModelQuality[mix] := Quality;
     1758            if (Cat >= 0) and (Quality > ModelBestQuality[Cat]) then
     1759              ModelBestQuality[Cat] := Quality;
    15881760          end;
    1589       mkSpecial_TownGuard: mixTownGuard:=mix;
    1590       mkSettler: mixSettlers:=mix; // engineers always have higher mix
    1591       mkCaravan: mixCaravan:=mix;
    1592       mkSlaves: mixSlaves:=mix
    1593       end
    1594   end;
    1595 
    1596 // mark obsolete models with quality=0
    1597 for mix:=0 to RO.nModel-1 do
    1598   if (MyModel[mix].Kind<$10) and (ModelCat[mix]>=0)
    1599     and (ModelQuality[mix]+MaxExistWorseThanBestModel
    1600       < ModelBestQuality[ModelCat[mix]]) then
    1601     ModelQuality[mix]:=ModelQuality[mix]-$40000000;
    1602 
    1603 OceanWithShip:=0;
    1604 if mixCruiser>=0 then
    1605   for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    1606     if (Loc>=0) and (mix=mixCruiser) and (Map[Loc] and fTerrain<fGrass) then
    1607       begin
    1608       i:=Formation[Loc];
    1609       if (i>=0) and (i<maxCOD) then OceanWithShip:=OceanWithShip or (1 shl i)
    1610       end;
     1761        mkSpecial_TownGuard: mixTownGuard := mix;
     1762        mkSettler: mixSettlers := mix; // engineers always have higher mix
     1763        mkCaravan: mixCaravan := mix;
     1764        mkSlaves: mixSlaves := mix
     1765      end;
     1766  end;
     1767
     1768  // mark obsolete models with quality=0
     1769  for mix := 0 to RO.nModel - 1 do
     1770    if (MyModel[mix].Kind < $10) and (ModelCat[mix] >= 0) and
     1771      (ModelQuality[mix] + MaxExistWorseThanBestModel <
     1772      ModelBestQuality[ModelCat[mix]]) then
     1773      ModelQuality[mix] := ModelQuality[mix] - $40000000;
     1774
     1775  OceanWithShip := 0;
     1776  if mixCruiser >= 0 then
     1777    for uix := 0 to RO.nUn - 1 do
     1778      with MyUnit[uix] do
     1779        if (Loc >= 0) and (mix = mixCruiser) and (Map[Loc] and fTerrain < fGrass) then
     1780        begin
     1781          i := Formation[Loc];
     1782          if (i >= 0) and (i < maxCOD) then
     1783            OceanWithShip := OceanWithShip or (1 shl i);
     1784        end;
    16111785end;
    16121786
     
    16141788procedure TAI.MoveUnitsHome;
    16151789const
    1616 PatrolDestination=lxmax*lymax;
    1617 FirstSurplusLoop: array[mctGroundDefender..mctGroundAttacker] of integer= (2,1);
     1790  PatrolDestination = lxmax * lymax;
     1791  FirstSurplusLoop: array[mctGroundDefender..mctGroundAttacker] of integer = (2, 1);
    16181792var
    1619 Cat,i,mix,cix,uix,Loop,nModelOrder: integer;
    1620 Adjacent: TVicinity8Loc;
    1621 LocNeed: array[0..lxmax*lymax-1] of shortint;
    1622 Destination: array[0..nUmax-1] of integer;
    1623 DistrictNeed,DistrictNeed0: array[0..maxCOD-1] of integer;
    1624 ModelOrder: array[0..nMmax-1] of integer;
    1625 complete,Fortified: boolean;
     1793  Cat, i, mix, cix, uix, Loop, nModelOrder: integer;
     1794  Adjacent: TVicinity8Loc;
     1795  LocNeed: array[0..lxmax * lymax - 1] of shortint;
     1796  Destination: array[0..nUmax - 1] of integer;
     1797  DistrictNeed, DistrictNeed0: array[0..maxCOD - 1] of integer;
     1798  ModelOrder: array[0..nMmax - 1] of integer;
     1799  complete, Fortified: boolean;
    16261800
    16271801  function IsBombarded(cix: integer): boolean;
    16281802  var
    1629   Loc1,V8: integer;
    1630   Adjacent: TVicinity8Loc;
    1631   begin
    1632   result:=false;
    1633   if BombardingNations<>0 then with MyCity[cix] do
    1634     begin
    1635     V8_to_Loc(Loc,Adjacent);
    1636     for V8:=0 to 7 do
    1637       begin
    1638       Loc1:=Adjacent[V8];
    1639       if (Loc1>=0) and (Map[Loc1] and fTerrain<fGrass)
    1640         and (Formation[Loc1]>=0) and (Formation[Loc1]<maxCOD)
    1641         and (OceanPresence[Formation[Loc1]] and (BombardingNations or PresenceUnknown)<>0) then
    1642         begin result:=true; exit end
    1643       end;
    1644     end;
     1803    Loc1, V8: integer;
     1804    Adjacent: TVicinity8Loc;
     1805  begin
     1806    Result := False;
     1807    if BombardingNations <> 0 then
     1808      with MyCity[cix] do
     1809      begin
     1810        V8_to_Loc(Loc, Adjacent);
     1811        for V8 := 0 to 7 do
     1812        begin
     1813          Loc1 := Adjacent[V8];
     1814          if (Loc1 >= 0) and (Map[Loc1] and fTerrain < fGrass) and
     1815            (Formation[Loc1] >= 0) and (Formation[Loc1] < maxCOD) and
     1816            (OceanPresence[Formation[Loc1]] and (BombardingNations or
     1817            PresenceUnknown) <> 0) then
     1818          begin
     1819            Result := True;
     1820            exit;
     1821          end;
     1822        end;
     1823      end;
    16451824  end;
    16461825
    16471826  procedure TryUtilize(uix: integer);
    16481827  var
    1649   cix, ProdCost, UtilizeCost: integer;
    1650   begin
    1651   if (MyUnit[uix].Health=100)
    1652     and (Map[MyUnit[uix].Loc] and (fCity or fOwned)=fCity or fOwned) then
    1653     begin
    1654     City_FindMyCity(MyUnit[uix].Loc,cix);
    1655     with MyCity[cix] do if Project and cpImp=0 then
    1656       begin
    1657       ProdCost:=MyModel[Project and cpIndex].Cost;
    1658       UtilizeCost:=MyModel[MyUnit[uix].mix].Cost;
    1659       if Prod<(ProdCost-UtilizeCost*2 div 3)*BuildCostMod[G.Difficulty[me]] div 12 then
    1660         Unit_Disband(uix);
    1661       end
    1662     end
     1828    cix, ProdCost, UtilizeCost: integer;
     1829  begin
     1830    if (MyUnit[uix].Health = 100) and (Map[MyUnit[uix].Loc] and
     1831      (fCity or fOwned) = fCity or fOwned) then
     1832    begin
     1833      City_FindMyCity(MyUnit[uix].Loc, cix);
     1834      with MyCity[cix] do
     1835        if Project and cpImp = 0 then
     1836        begin
     1837          ProdCost := MyModel[Project and cpIndex].Cost;
     1838          UtilizeCost := MyModel[MyUnit[uix].mix].Cost;
     1839          if Prod < (ProdCost - UtilizeCost * 2 div 3) *
     1840            BuildCostMod[G.Difficulty[me]] div 12 then
     1841            Unit_Disband(uix);
     1842        end;
     1843    end;
    16631844  end;
    16641845
    16651846  procedure FindDestination(uix: integer);
    16661847  var
    1667   MoveStyle,V8,Loc1,Time,NextLoc,NextTime,RecoverTurns: integer;
    1668   Reached: array[0..lxmax*lymax-1] of boolean;
    1669   begin
    1670   fillchar(Reached, MapSize, false);
    1671   Pile.Create(MapSize);
    1672   with MyUnit[uix] do
    1673     begin
    1674     Pile.Put(Loc, $800-Movement);
    1675     MoveStyle:=GetMyMoveStyle(mix, 100);
    1676     end;
    1677   while Pile.Get(Loc1, Time) do
    1678     begin
    1679     if LocNeed[Loc1]>0 then
    1680       begin
    1681       LocNeed[Loc1]:=0;
    1682       if (District[Loc1]>=0) and (District[Loc1]<maxCOD) then
    1683         begin
    1684         assert(DistrictNeed[District[Loc1]]>0);
    1685         dec(DistrictNeed[District[Loc1]]);
    1686         end;
    1687       Destination[uix]:=Loc1;
    1688       break;
    1689       end;
    1690     Reached[Loc1]:=true;
    1691     V8_to_Loc(Loc1, Adjacent);
    1692     for V8:=0 to 7 do
    1693       begin
    1694       NextLoc:=Adjacent[V8];
    1695       if (NextLoc>=0) and not Reached[NextLoc] and (RO.Territory[NextLoc]=me) then
    1696         case CheckStep(MoveStyle, Time, V8 and 1, NextTime, RecoverTurns, Map[Loc1], Map[NextLoc], false) of
    1697           csOk:
    1698             Pile.Put(NextLoc, NextTime);
    1699           csForbiddenTile:
    1700             Reached[NextLoc]:=true; // don't check moving there again
    1701           csCheckTerritory:
    1702             assert(false);
    1703           end
    1704       end;
    1705     end;
    1706   Pile.Free;
     1848    MoveStyle, V8, Loc1, Time, NextLoc, NextTime, RecoverTurns: integer;
     1849    Reached: array[0..lxmax * lymax - 1] of boolean;
     1850  begin
     1851    fillchar(Reached, MapSize, False);
     1852    Pile.Create(MapSize);
     1853    with MyUnit[uix] do
     1854    begin
     1855      Pile.Put(Loc, $800 - Movement);
     1856      MoveStyle := GetMyMoveStyle(mix, 100);
     1857    end;
     1858    while Pile.Get(Loc1, Time) do
     1859    begin
     1860      if LocNeed[Loc1] > 0 then
     1861      begin
     1862        LocNeed[Loc1] := 0;
     1863        if (District[Loc1] >= 0) and (District[Loc1] < maxCOD) then
     1864        begin
     1865          assert(DistrictNeed[District[Loc1]] > 0);
     1866          Dec(DistrictNeed[District[Loc1]]);
     1867        end;
     1868        Destination[uix] := Loc1;
     1869        break;
     1870      end;
     1871      Reached[Loc1] := True;
     1872      V8_to_Loc(Loc1, Adjacent);
     1873      for V8 := 0 to 7 do
     1874      begin
     1875        NextLoc := Adjacent[V8];
     1876        if (NextLoc >= 0) and not Reached[NextLoc] and (RO.Territory[NextLoc] = me) then
     1877          case CheckStep(MoveStyle, Time, V8 and 1, NextTime, RecoverTurns,
     1878              Map[Loc1], Map[NextLoc], False) of
     1879            csOk:
     1880              Pile.Put(NextLoc, NextTime);
     1881            csForbiddenTile:
     1882              Reached[NextLoc] := True; // don't check moving there again
     1883            csCheckTerritory:
     1884              assert(False);
     1885          end;
     1886      end;
     1887    end;
     1888    Pile.Free;
    17071889  end;
    17081890
    17091891begin
    1710 if not (RO.Government in [gAnarchy, gDespotism]) then // utilize townguards
    1711   for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    1712     if (Loc>=0) and (Master<0) and (mix=mixTownGuard) then
    1713     Unit_Disband(uix);
    1714 
    1715 fillchar(UnitLack,sizeof(UnitLack),0);
    1716 fillchar(Destination, 4*RO.nUn, $FF);
    1717 for i:=0 to maxCOD-1 do
    1718   if uixPatrol[i]>=0 then
    1719     Destination[uixPatrol[i]]:=PatrolDestination;
    1720 for uix:=0 to RO.nUn-1 do
    1721   if (MyUnit[uix].mix=mixMilitia) or (MyUnit[uix].mix=mixCruiser) then
    1722     Destination[uix]:=PatrolDestination;
    1723 
    1724 // distribute attackers and defenders
    1725 for Cat:=mctGroundDefender to mctGroundAttacker do
    1726   begin
    1727   nModelOrder:=0;
    1728   for mix:=0 to Ro.nModel-1 do
    1729     if ModelCat[mix]=Cat then
    1730       begin
    1731       i:=nModelOrder;
    1732       while (i>0) and (ModelQuality[mix]<ModelQuality[ModelOrder[i-1]]) do
    1733         begin ModelOrder[i]:=ModelOrder[i-1]; dec(i) end;
    1734       ModelOrder[i]:=mix;
    1735       inc(nModelOrder);
    1736       end;
    1737 
    1738   Loop:=0;
     1892  if not (RO.Government in [gAnarchy, gDespotism]) then // utilize townguards
     1893    for uix := 0 to RO.nUn - 1 do
     1894      with MyUnit[uix] do
     1895        if (Loc >= 0) and (Master < 0) and (mix = mixTownGuard) then
     1896          Unit_Disband(uix);
     1897
     1898  fillchar(UnitLack, sizeof(UnitLack), 0);
     1899  fillchar(Destination, 4 * RO.nUn, $FF);
     1900  for i := 0 to maxCOD - 1 do
     1901    if uixPatrol[i] >= 0 then
     1902      Destination[uixPatrol[i]] := PatrolDestination;
     1903  for uix := 0 to RO.nUn - 1 do
     1904    if (MyUnit[uix].mix = mixMilitia) or (MyUnit[uix].mix = mixCruiser) then
     1905      Destination[uix] := PatrolDestination;
     1906
     1907  // distribute attackers and defenders
     1908  for Cat := mctGroundDefender to mctGroundAttacker do
     1909  begin
     1910    nModelOrder := 0;
     1911    for mix := 0 to Ro.nModel - 1 do
     1912      if ModelCat[mix] = Cat then
     1913      begin
     1914        i := nModelOrder;
     1915        while (i > 0) and (ModelQuality[mix] < ModelQuality[ModelOrder[i - 1]]) do
     1916        begin
     1917          ModelOrder[i] := ModelOrder[i - 1];
     1918          Dec(i);
     1919        end;
     1920        ModelOrder[i] := mix;
     1921        Inc(nModelOrder);
     1922      end;
     1923
     1924    Loop := 0;
     1925    repeat
     1926      if Loop = FirstSurplusLoop[Cat] then
     1927        for uix := 0 to RO.nUn - 1 do
     1928          with MyUnit[uix] do
     1929            if (Loc >= 0) and (Destination[uix] < 0) and (Master < 0) and
     1930              (ModelCat[mix] = Cat) and (ModelQuality[mix] < 0) then
     1931              TryUtilize(uix);
     1932
     1933      fillchar(LocNeed, MapSize, 0);
     1934      fillchar(DistrictNeed, sizeof(DistrictNeed), 0);
     1935
     1936      for cix := 0 to RO.nCity - 1 do
     1937        with MyCity[cix] do
     1938          if Loc >= 0 then
     1939            if ((Cat <> mctGroundDefender) or (Loop <> 0) or IsBombarded(cix)) and
     1940              ((Loop <> FirstSurplusLoop[Cat]) or
     1941              (Built[imBarracks] + Built[imMilAcademy] > 0)) and
     1942              ((Loop <> FirstSurplusLoop[Cat] + 1) or
     1943              (Built[imBarracks] + Built[imMilAcademy] = 0)) then
     1944            begin
     1945              LocNeed[Loc] := 1;
     1946              if (District[Loc] >= 0) and (District[Loc] < maxCOD) then
     1947              begin
     1948                Inc(DistrictNeed[District[Loc]]);
     1949                if Loop < FirstSurplusLoop[Cat] then
     1950                  Inc(UnitLack[District[Loc], Cat]);
     1951              end;
     1952            end;
     1953
     1954      if Loop = 0 then // protect city building sites
     1955        for uix := 0 to RO.nUn - 1 do
     1956          with MyUnit[uix] do
     1957            if (Loc >= 0) and (Job = jCity) and (RO.Territory[Loc] = me) then
     1958            begin
     1959              LocNeed[Loc] := 1;
     1960              if (District[Loc] >= 0) and (District[Loc] < maxCOD) then
     1961                Inc(DistrictNeed[District[Loc]]);
     1962            end;
     1963
     1964      complete := Loop >= FirstSurplusLoop[Cat];
     1965      for i := nModelOrder - 1 downto 0 do
     1966      begin
     1967        for Fortified := True downto False do
     1968          for uix := 0 to RO.nUn - 1 do
     1969            with MyUnit[uix] do
     1970              if (mix = ModelOrder[i]) and (Loc >= 0) and
     1971                (Destination[uix] < 0) and (Master < 0) and
     1972                ((Flags and unFortified <> 0) = Fortified) and (LocNeed[Loc] > 0) then
     1973              begin
     1974                LocNeed[Loc] := 0;
     1975                if (District[Loc] >= 0) and (District[Loc] < maxCOD) then
     1976                  Dec(DistrictNeed[District[Loc]]);
     1977                Destination[uix] := Loc;
     1978                complete := False;
     1979              end;
     1980
     1981        for uix := 0 to RO.nUn - 1 do
     1982          with MyUnit[uix] do
     1983            if (mix = ModelOrder[i]) and (Loc >= 0) and (Destination[uix] < 0) and
     1984              (Master < 0) then
     1985              if (District[Loc] >= 0) and (District[Loc] < maxCOD) and
     1986                (DistrictNeed[District[Loc]] = 0) then
     1987              else
     1988              begin // unassigned unit
     1989                FindDestination(uix);
     1990                if Destination[uix] >= 0 then
     1991                  complete := False;
     1992              end;
     1993      end;
     1994      Inc(Loop)
     1995    until complete;
     1996  end;
     1997
     1998  // distribute obsolete settlers
    17391999  repeat
    1740     if Loop=FirstSurplusLoop[Cat] then
    1741       for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    1742         if (Loc>=0) and (Destination[uix]<0) and (Master<0)
    1743           and (ModelCat[mix]=Cat)
    1744           and (ModelQuality[mix]<0) then
    1745           TryUtilize(uix);
    1746 
    17472000    fillchar(LocNeed, MapSize, 0);
    17482001    fillchar(DistrictNeed, sizeof(DistrictNeed), 0);
    17492002
    1750     for cix:=0 to RO.nCity-1 do with MyCity[cix] do if Loc>=0 then
    1751       if ((Cat<>mctGroundDefender) or (Loop<>0) or IsBombarded(cix))
    1752         and ((Loop<>FirstSurplusLoop[Cat]) or (Built[imBarracks]+Built[imMilAcademy]>0))
    1753         and ((Loop<>FirstSurplusLoop[Cat]+1) or (Built[imBarracks]+Built[imMilAcademy]=0)) then
    1754         begin
    1755         LocNeed[Loc]:=1;
    1756         if (District[Loc]>=0) and (District[Loc]<maxCOD) then
     2003    for cix := 0 to RO.nCity - 1 do
     2004      with MyCity[cix] do
     2005        if Loc >= 0 then
     2006          if (Built[imSewer] > 0) or (Built[imAqueduct] > 0) and
     2007            (Size <= NeedSewerSize - 2) or (Size <= NeedAqueductSize - 2) or
     2008            (Project = mixSettlers) then
    17572009          begin
    1758           inc(DistrictNeed[District[Loc]]);
    1759           if Loop<FirstSurplusLoop[Cat] then
    1760             inc(UnitLack[District[Loc],Cat])
    1761           end
    1762         end;
    1763 
    1764     if Loop=0 then // protect city building sites
    1765       for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    1766         if (Loc>=0) and (Job=jCity) and (RO.Territory[Loc]=me) then
    1767           begin
    1768           LocNeed[Loc]:=1;
    1769           if (District[Loc]>=0) and (District[Loc]<maxCOD) then
    1770             inc(DistrictNeed[District[Loc]]);
     2010            LocNeed[Loc] := 1;
     2011            if (District[Loc] >= 0) and (District[Loc] < maxCOD) then
     2012              Inc(DistrictNeed[District[Loc]]);
    17712013          end;
    1772 
    1773     complete:= Loop>=FirstSurplusLoop[Cat];
    1774     for i:=nModelOrder-1 downto 0 do
    1775       begin
    1776       for Fortified:=true downto false do
    1777         for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    1778           if (mix=ModelOrder[i])
    1779             and (Loc>=0) and (Destination[uix]<0) and (Master<0)
    1780             and ((Flags and unFortified<>0) = Fortified)
    1781             and (LocNeed[Loc]>0) then
     2014    DistrictNeed0 := DistrictNeed;
     2015
     2016    complete := True;
     2017    for uix := 0 to RO.nUn - 1 do
     2018      with MyUnit[uix] do
     2019        if (Loc >= 0) and (Destination[uix] < 0) and (Master < 0) then
     2020          if (MyModel[mix].Kind = mkSettler) and (mix <> mixSettlers) and
     2021            (Job = jNone) then
     2022            if (District[Loc] >= 0) and (District[Loc] < maxCOD) and
     2023              (DistrictNeed[District[Loc]] = 0) then
    17822024            begin
    1783             LocNeed[Loc]:=0;
    1784             if (District[Loc]>=0) and (District[Loc]<maxCOD) then
    1785               dec(DistrictNeed[District[Loc]]);
    1786             Destination[uix]:=Loc;
    1787             complete:=false;
     2025              if DistrictNeed0[District[Loc]] > 0 then
     2026                complete := False;
     2027            end
     2028            else
     2029            begin // unassigned unit
     2030              FindDestination(uix);
     2031              //          if (Destination[uix]<0) and (RO.Territory[Loc]=me) then
     2032              //            complete:=false; // causes hangup when unit can't move due to zoc
    17882033            end;
    1789 
    1790       for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    1791         if (mix=ModelOrder[i])
    1792           and (Loc>=0) and (Destination[uix]<0) and (Master<0) then
    1793           if (District[Loc]>=0) and (District[Loc]<maxCOD)
    1794             and (DistrictNeed[District[Loc]]=0) then
    1795           else
    1796             begin // unassigned unit
    1797             FindDestination(uix);
    1798             if Destination[uix]>=0 then complete:=false;
    1799             end;
    1800       end;
    1801     inc(Loop)
    18022034  until complete;
    1803   end;
    1804 
    1805 // distribute obsolete settlers
    1806 repeat
    1807   fillchar(LocNeed, MapSize, 0);
    1808   fillchar(DistrictNeed, sizeof(DistrictNeed), 0);
    1809 
    1810   for cix:=0 to RO.nCity-1 do with MyCity[cix] do if Loc>=0 then
    1811     if (Built[imSewer]>0)
    1812       or (Built[imAqueduct]>0) and (Size<=NeedSewerSize-2)
    1813       or (Size<=NeedAqueductSize-2)
    1814       or (Project=mixSettlers) then
    1815       begin
    1816       LocNeed[Loc]:=1;
    1817       if (District[Loc]>=0) and (District[Loc]<maxCOD) then
    1818         inc(DistrictNeed[District[Loc]]);
    1819       end;
    1820   DistrictNeed0:=DistrictNeed;
    1821 
    1822   complete:=true;
    1823   for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    1824     if (Loc>=0) and (Destination[uix]<0) and (Master<0) then
    1825       if (MyModel[mix].Kind=mkSettler) and (mix<>mixSettlers)
    1826         and (Job=jNone) then
    1827         if (District[Loc]>=0) and (District[Loc]<maxCOD)
    1828           and (DistrictNeed[District[Loc]]=0) then
    1829           begin
    1830           if DistrictNeed0[District[Loc]]>0 then
    1831             complete:=false
    1832           end
    1833         else
    1834           begin // unassigned unit
    1835           FindDestination(uix);
    1836 //          if (Destination[uix]<0) and (RO.Territory[Loc]=me) then
    1837 //            complete:=false; // causes hangup when unit can't move due to zoc
    1838           end;
    1839 until complete;
    1840 
    1841 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do if Loc>=0 then
    1842   if Destination[uix]<0 then
    1843     begin
    1844     if (MyModel[mix].Kind<>mkSettler) and (MyModel[mix].Kind<>mkSlaves)
    1845       and (Master<0) and (Map[Loc] and fCity=0) then
    1846       Unit_MoveEx(uix, maNextCity);
    1847     end
    1848   else if (Destination[uix]<>PatrolDestination) and (Loc<>Destination[uix]) then
    1849     Unit_MoveEx(uix, Destination[uix]);
    1850 
    1851 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    1852   if (Loc>=0) and (RO.Territory[Loc]=me)
    1853     and (District[Loc]>=0) and (District[Loc]<maxCOD)
    1854     and (ModelQuality[mix]>0) then
    1855     case ModelCat[mix] of
    1856       mctGroundDefender,mctGroundAttacker:
    1857         dec(UnitLack[District[Loc],ModelCat[mix]])
    1858       end;
     2035
     2036  for uix := 0 to RO.nUn - 1 do
     2037    with MyUnit[uix] do
     2038      if Loc >= 0 then
     2039        if Destination[uix] < 0 then
     2040        begin
     2041          if (MyModel[mix].Kind <> mkSettler) and (MyModel[mix].Kind <> mkSlaves) and
     2042            (Master < 0) and (Map[Loc] and fCity = 0) then
     2043            Unit_MoveEx(uix, maNextCity);
     2044        end
     2045        else if (Destination[uix] <> PatrolDestination) and
     2046          (Loc <> Destination[uix]) then
     2047          Unit_MoveEx(uix, Destination[uix]);
     2048
     2049  for uix := 0 to RO.nUn - 1 do
     2050    with MyUnit[uix] do
     2051      if (Loc >= 0) and (RO.Territory[Loc] = me) and (District[Loc] >= 0) and
     2052        (District[Loc] < maxCOD) and (ModelQuality[mix] > 0) then
     2053        case ModelCat[mix] of
     2054          mctGroundDefender, mctGroundAttacker:
     2055            Dec(UnitLack[District[Loc], ModelCat[mix]])
     2056        end;
    18592057end; // MoveUnitsHome
    18602058
     
    18622060procedure TAI.CheckAttack(uix: integer);
    18632061var
    1864 AttackScore,BestCount,AttackLoc,TestLoc,NextLoc,TestTime,V8,
    1865   TestScore,euix,MyDamage,EnemyDamage,OldLoc,
    1866   AttackForecast,MoveResult,AttackResult,MoveStyle,NextTime,RecoverTurns: integer;
    1867 Tile: Cardinal;
    1868 Exhausted: boolean;
    1869 Adjacent: TVicinity8Loc;
    1870 Reached: array[0..lxmax*lymax-1] of boolean;
     2062  AttackScore, BestCount, AttackLoc, TestLoc, NextLoc, TestTime, V8,
     2063  TestScore, euix, MyDamage, EnemyDamage, OldLoc, AttackForecast,
     2064  MoveResult, AttackResult, MoveStyle, NextTime, RecoverTurns: integer;
     2065  Tile: cardinal;
     2066  Exhausted: boolean;
     2067  Adjacent: TVicinity8Loc;
     2068  Reached: array[0..lxmax * lymax - 1] of boolean;
    18712069
    18722070begin
    1873 with MyUnit[uix] do
    1874   begin
    1875   MoveStyle:=GetMyMoveStyle(mix,Health);
    1876   repeat
    1877     AttackScore:=-999999;
    1878     AttackLoc:=-1;
    1879     fillchar(Reached, MapSize, false);
    1880     Pile.Create(MapSize);
    1881     Pile.Put(Loc, $800-Movement); // start search for something to do at current location
    1882     while Pile.Get(TestLoc,TestTime) do
    1883       begin
    1884       TestScore:=0;
    1885       Tile:=Map[TestLoc];
    1886       Reached[TestLoc]:=true;
    1887 
    1888       if ((Tile and fUnit)<>0) and ((Tile and fOwned)=0) then
     2071  with MyUnit[uix] do
     2072  begin
     2073    MoveStyle := GetMyMoveStyle(mix, Health);
     2074    repeat
     2075      AttackScore := -999999;
     2076      AttackLoc := -1;
     2077      fillchar(Reached, MapSize, False);
     2078      Pile.Create(MapSize);
     2079      Pile.Put(Loc, $800 - Movement);
     2080      // start search for something to do at current location
     2081      while Pile.Get(TestLoc, TestTime) do
     2082      begin
     2083        TestScore := 0;
     2084        Tile := Map[TestLoc];
     2085        Reached[TestLoc] := True;
     2086
     2087        if ((Tile and fUnit) <> 0) and ((Tile and fOwned) = 0) then
    18892088        begin // enemy unit
    1890         assert(TestTime<$1000);
    1891         Unit_FindEnemyDefender(TestLoc,euix);
    1892         if RO.Treaty[RO.EnemyUn[euix].Owner]<trPeace then
    1893           if Unit_AttackForecast(uix,TestLoc,$800-TestTime,AttackForecast) then
     2089          assert(TestTime < $1000);
     2090          Unit_FindEnemyDefender(TestLoc, euix);
     2091          if RO.Treaty[RO.EnemyUn[euix].Owner] < trPeace then
     2092            if Unit_AttackForecast(uix, TestLoc, $800 - TestTime, AttackForecast) then
    18942093            begin // attack possible, but advantageous?
    1895             if AttackForecast=0 then
     2094              if AttackForecast = 0 then
    18962095              begin // enemy unit would be destroyed
    1897               MyDamage:=Health+DestroyBonus;
    1898               EnemyDamage:=RO.EnemyUn[euix].Health+DestroyBonus;
     2096                MyDamage := Health + DestroyBonus;
     2097                EnemyDamage := RO.EnemyUn[euix].Health + DestroyBonus;
    18992098              end
    1900             else if AttackForecast>0 then
     2099              else if AttackForecast > 0 then
    19012100              begin // enemy unit would be destroyed
    1902               MyDamage:=Health-AttackForecast;
    1903               EnemyDamage:=RO.EnemyUn[euix].Health+DestroyBonus;
     2101                MyDamage := Health - AttackForecast;
     2102                EnemyDamage := RO.EnemyUn[euix].Health + DestroyBonus;
    19042103              end
    1905             else // own unit would be destroyed
     2104              else // own unit would be destroyed
    19062105              begin
    1907               MyDamage:=Health+DestroyBonus;
    1908               EnemyDamage:=RO.EnemyUn[euix].Health+AttackForecast;
     2106                MyDamage := Health + DestroyBonus;
     2107                EnemyDamage := RO.EnemyUn[euix].Health + AttackForecast;
    19092108              end;
    1910             TestScore:=Aggressive*2
    1911               *(EnemyDamage*RO.EnemyModel[RO.EnemyUn[euix].emix].Cost)
    1912               div (MyDamage*MyModel[mix].Cost);
    1913             if TestScore<=100 then TestScore:=0 // own losses exceed enemy losses, no good
    1914             else
     2109              TestScore := Aggressive * 2 *
     2110                (EnemyDamage * RO.EnemyModel[RO.EnemyUn[euix].emix].Cost) div
     2111                (MyDamage * MyModel[mix].Cost);
     2112              if TestScore <= 100 then
     2113                TestScore := 0 // own losses exceed enemy losses, no good
     2114              else
    19152115              begin
    1916               if TestScore>AttackScore then
    1917                 BestCount:=0;
    1918               if TestScore>=AttackScore then
     2116                if TestScore > AttackScore then
     2117                  BestCount := 0;
     2118                if TestScore >= AttackScore then
    19192119                begin
    1920                 inc(BestCount);
    1921                 if random(BestCount)=0 then
     2120                  Inc(BestCount);
     2121                  if random(BestCount) = 0 then
    19222122                  begin
    1923                   AttackScore:=TestScore;
    1924                   AttackLoc:=TestLoc;
    1925                   end
     2123                    AttackScore := TestScore;
     2124                    AttackLoc := TestLoc;
     2125                  end;
    19262126                end;
    1927               end
     2127              end;
    19282128            end;
    19292129        end // enemy unit
    19302130
    1931       else if ((Tile and fCity)<>0) and ((Tile and fOwned)=0) then
     2131        else if ((Tile and fCity) <> 0) and ((Tile and fOwned) = 0) then
    19322132        // enemy city
    19332133
    1934       else
     2134        else
    19352135        begin // no enemy city or unit here
    1936         V8_to_Loc(TestLoc,Adjacent);
    1937         for V8:=0 to 7 do
     2136          V8_to_Loc(TestLoc, Adjacent);
     2137          for V8 := 0 to 7 do
    19382138          begin
    1939           NextLoc:=Adjacent[V8];
    1940           if (NextLoc>=0) and not Reached[NextLoc]
    1941             and (Map[NextLoc] and fTerrain<>fUNKNOWN) then
    1942             if Map[NextLoc] and (fUnit or fOwned)=fUnit then
    1943               Pile.Put(NextLoc, TestTime) // foreign unit!
    1944             else case CheckStep(MoveStyle, TestTime, V8 and 1, NextTime,
    1945               RecoverTurns, Map[Loc], Map[NextLoc], true) of
    1946               csOk,csCheckTerritory:
    1947                 if NextTime<$1000 then Pile.Put(NextLoc, NextTime);
    1948               csForbiddenTile:
    1949                 Reached[NextLoc]:=true; // don't check moving there again
    1950               end
     2139            NextLoc := Adjacent[V8];
     2140            if (NextLoc >= 0) and not Reached[NextLoc] and
     2141              (Map[NextLoc] and fTerrain <> fUNKNOWN) then
     2142              if Map[NextLoc] and (fUnit or fOwned) = fUnit then
     2143                Pile.Put(NextLoc, TestTime) // foreign unit!
     2144              else
     2145                case CheckStep(MoveStyle, TestTime, V8 and 1, NextTime,
     2146                    RecoverTurns, Map[Loc], Map[NextLoc], True) of
     2147                  csOk, csCheckTerritory:
     2148                    if NextTime < $1000 then
     2149                      Pile.Put(NextLoc, NextTime);
     2150                  csForbiddenTile:
     2151                    Reached[NextLoc] := True; // don't check moving there again
     2152                end;
    19512153          end;
    19522154        end; // no enemy city or unit here
    19532155      end; // while Pile.Get
    1954     Pile.Free;
    1955 
    1956     if AttackLoc>=0 then
    1957       begin
    1958       OldLoc:=Loc;
    1959       MoveResult:=Unit_Move(uix,AttackLoc);
    1960       Exhausted:= (Loc=OldLoc)
    1961         or ((MoveResult and (rMoreTurns or rUnitRemoved))<>0);
    1962       if MoveResult and rLocationReached<>0 then
    1963         if Movement<100 then
    1964           Exhausted:=true
    1965         else
     2156      Pile.Free;
     2157
     2158      if AttackLoc >= 0 then
     2159      begin
     2160        OldLoc := Loc;
     2161        MoveResult := Unit_Move(uix, AttackLoc);
     2162        Exhausted := (Loc = OldLoc) or
     2163          ((MoveResult and (rMoreTurns or rUnitRemoved)) <> 0);
     2164        if MoveResult and rLocationReached <> 0 then
     2165          if Movement < 100 then
     2166            Exhausted := True
     2167          else
    19662168          begin
    1967           AttackResult:=Unit_Attack(uix,AttackLoc);
    1968           Exhausted:= ((AttackResult and rExecuted)=0)
    1969             or ((AttackResult and rUnitRemoved)<>0);
     2169            AttackResult := Unit_Attack(uix, AttackLoc);
     2170            Exhausted := ((AttackResult and rExecuted) = 0) or
     2171              ((AttackResult and rUnitRemoved) <> 0);
    19702172          end;
    19712173      end
    1972     else Exhausted:=true;
    1973   until Exhausted;
     2174      else
     2175        Exhausted := True;
     2176    until Exhausted;
    19742177  end;
    19752178end; // CheckAttack
     
    19782181procedure TAI.Patrol(uix: integer);
    19792182const
    1980 DistanceScore=4;
     2183  DistanceScore = 4;
    19812184var
    1982 PatrolScore,BestCount,PatrolLoc,TestLoc,NextLoc,TestTime,V8,
    1983   TestScore,OldLoc,MoveResult,MoveStyle,NextTime,RecoverTurns: integer;
    1984 Tile: Cardinal;
    1985 Exhausted,CaptureOnly: boolean;
    1986 Adjacent: TVicinity8Loc;
    1987 AdjacentUnknown: array[0..lxmax*lymax-1] of shortint;
     2185  PatrolScore, BestCount, PatrolLoc, TestLoc, NextLoc, TestTime, V8,
     2186  TestScore, OldLoc, MoveResult, MoveStyle, NextTime, RecoverTurns: integer;
     2187  Tile: cardinal;
     2188  Exhausted, CaptureOnly: boolean;
     2189  Adjacent: TVicinity8Loc;
     2190  AdjacentUnknown: array[0..lxmax * lymax - 1] of shortint;
    19882191
    19892192begin
    1990 with MyUnit[uix] do
    1991   begin
    1992   CaptureOnly:= ((100-Health)*Terrain[Map[Loc] and fTerrain].Defense>60)
    1993     and not (Map[Loc] and fTerrain in [fOcean, fShore, fArctic, fDesert]);
    1994   MoveStyle:=GetMyMoveStyle(mix, Health);
    1995   repeat
    1996     PatrolScore:=-999999;
    1997     PatrolLoc:=-1;
    1998     FillChar(AdjacentUnknown,MapSize,$FF); // -1, indicates tiles not checked yet
    1999     Pile.Create(MapSize);
    2000     Pile.Put(Loc, $800-Movement);
    2001     while Pile.Get(TestLoc,TestTime) do
    2002       begin
    2003       if (50*$1000-DistanceScore*TestTime<=PatrolScore) // assume a score of 50 is the best achievable
    2004         or CaptureOnly and (TestTime>=$1000) then
    2005         break;
    2006 
    2007       TestScore:=0;
    2008       Tile:=Map[TestLoc];
    2009       AdjacentUnknown[TestLoc]:=0;
    2010 
    2011       if ((Tile and fUnit)<>0) and ((Tile and fOwned)=0) then
     2193  with MyUnit[uix] do
     2194  begin
     2195    CaptureOnly := ((100 - Health) * Terrain[Map[Loc] and fTerrain].Defense > 60) and
     2196      not (Map[Loc] and fTerrain in [fOcean, fShore, fArctic, fDesert]);
     2197    MoveStyle := GetMyMoveStyle(mix, Health);
     2198    repeat
     2199      PatrolScore := -999999;
     2200      PatrolLoc := -1;
     2201      FillChar(AdjacentUnknown, MapSize, $FF); // -1, indicates tiles not checked yet
     2202      Pile.Create(MapSize);
     2203      Pile.Put(Loc, $800 - Movement);
     2204      while Pile.Get(TestLoc, TestTime) do
     2205      begin
     2206        if (50 * $1000 - DistanceScore * TestTime <= PatrolScore)
     2207          // assume a score of 50 is the best achievable
     2208          or CaptureOnly and (TestTime >= $1000) then
     2209          break;
     2210
     2211        TestScore := 0;
     2212        Tile := Map[TestLoc];
     2213        AdjacentUnknown[TestLoc] := 0;
     2214
     2215        if ((Tile and fUnit) <> 0) and ((Tile and fOwned) = 0) then
    20122216        // enemy unit
    20132217
    2014       else if ((Tile and fCity)<>0) and ((Tile and fOwned)=0) then
    2015         begin
    2016         if ((Tile and fObserved)<>0)
    2017           and (MyModel[mix].Domain=dGround) and (MyModel[mix].Attack>0)
    2018           and ((RO.Territory[TestLoc]<0) // happens only for unobserved cities of extinct tribes, new owner unknown
    2019             or (RO.Treaty[RO.Territory[TestLoc]]<trPeace)) then
    2020           TestScore:=40 // unfriendly undefended city -- capture!
     2218        else if ((Tile and fCity) <> 0) and ((Tile and fOwned) = 0) then
     2219        begin
     2220          if ((Tile and fObserved) <> 0) and (MyModel[mix].Domain = dGround) and
     2221            (MyModel[mix].Attack > 0) and ((RO.Territory[TestLoc] < 0)
     2222            // happens only for unobserved cities of extinct tribes, new owner unknown
     2223            or (RO.Treaty[RO.Territory[TestLoc]] < trPeace)) then
     2224            TestScore := 40; // unfriendly undefended city -- capture!
    20212225        end
    20222226
     2227        else
     2228        begin // no enemy city or unit here
     2229          V8_to_Loc(TestLoc, Adjacent);
     2230          for V8 := 0 to 7 do
     2231          begin
     2232            NextLoc := Adjacent[V8];
     2233            if (NextLoc >= 0) and (AdjacentUnknown[NextLoc] < 0) then
     2234              if Map[NextLoc] and fTerrain = fUNKNOWN then
     2235                Inc(AdjacentUnknown[TestLoc])
     2236              else if Formation[NextLoc] = Formation[TestLoc] then
     2237                case CheckStep(MoveStyle, TestTime, V8 and 1, NextTime,
     2238                    RecoverTurns, Map[TestLoc], Map[NextLoc], True) of
     2239                  csOk:
     2240                    Pile.Put(NextLoc, NextTime);
     2241                  csForbiddenTile:
     2242                    AdjacentUnknown[NextLoc] := 0; // don't check moving there again
     2243                  csCheckTerritory:
     2244                    if RO.Territory[NextLoc] = RO.Territory[TestLoc] then
     2245                      Pile.Put(NextLoc, NextTime);
     2246                end;
     2247          end;
     2248          if not CaptureOnly then
     2249            if AdjacentUnknown[TestLoc] > 0 then
     2250              TestScore := 20 + AdjacentUnknown[TestLoc]
     2251            else
     2252              TestScore := (RO.Turn - RO.MapObservedLast[TestLoc]) div 16;
     2253        end; // no enemy city or unit here
     2254
     2255        if TestScore > 0 then
     2256        begin
     2257          TestScore := TestScore * $1000 - DistanceScore * TestTime;
     2258          if TestScore > PatrolScore then
     2259            BestCount := 0;
     2260          if TestScore >= PatrolScore then
     2261          begin
     2262            Inc(BestCount);
     2263            if random(BestCount) = 0 then
     2264            begin
     2265              PatrolScore := TestScore;
     2266              PatrolLoc := TestLoc;
     2267            end;
     2268          end;
     2269        end;
     2270      end; // while Pile.Get
     2271      Pile.Free;
     2272
     2273      if PatrolLoc >= 0 then
     2274      begin // attack/capture/discover/patrol task found, execute it
     2275        OldLoc := Loc;
     2276        MoveResult := Unit_Move(uix, PatrolLoc);
     2277        Exhausted := (Loc = OldLoc) or
     2278          ((MoveResult and (rMoreTurns or rUnitRemoved)) <> 0);
     2279      end
    20232280      else
    2024         begin // no enemy city or unit here
    2025         V8_to_Loc(TestLoc,Adjacent);
    2026         for V8:=0 to 7 do
    2027           begin
    2028           NextLoc:=Adjacent[V8];
    2029           if (NextLoc>=0) and (AdjacentUnknown[NextLoc]<0) then
    2030             if Map[NextLoc] and fTerrain=fUNKNOWN then
    2031               inc(AdjacentUnknown[TestLoc])
    2032             else if Formation[NextLoc]=Formation[TestLoc] then
    2033               case CheckStep(MoveStyle, TestTime, V8 and 1, NextTime, RecoverTurns, Map[TestLoc], Map[NextLoc], true) of
    2034                 csOk:
    2035                   Pile.Put(NextLoc, NextTime);
    2036                 csForbiddenTile:
    2037                   AdjacentUnknown[NextLoc]:=0; // don't check moving there again
    2038                 csCheckTerritory:
    2039                   if RO.Territory[NextLoc]=RO.Territory[TestLoc] then
    2040                     Pile.Put(NextLoc, NextTime);
    2041                 end
    2042           end;
    2043         if not CaptureOnly then
    2044           if AdjacentUnknown[TestLoc]>0 then
    2045             TestScore:=20+AdjacentUnknown[TestLoc]
    2046           else TestScore:=(RO.Turn-RO.MapObservedLast[TestLoc]) div 16;
    2047         end; // no enemy city or unit here
    2048 
    2049       if TestScore>0 then
    2050         begin
    2051         TestScore:=TestScore*$1000-DistanceScore*TestTime;
    2052         if TestScore>PatrolScore then
    2053           BestCount:=0;
    2054         if TestScore>=PatrolScore then
    2055           begin
    2056           inc(BestCount);
    2057           if random(BestCount)=0 then
    2058             begin
    2059             PatrolScore:=TestScore;
    2060             PatrolLoc:=TestLoc;
    2061             end
    2062           end;
    2063         end
    2064       end; // while Pile.Get
    2065     Pile.Free;
    2066 
    2067     if PatrolLoc>=0 then
    2068       begin // attack/capture/discover/patrol task found, execute it
    2069       OldLoc:=Loc;
    2070       MoveResult:=Unit_Move(uix,PatrolLoc);
    2071       Exhausted:= (Loc=OldLoc)
    2072         or ((MoveResult and (rMoreTurns or rUnitRemoved))<>0);
    2073       end
    2074     else Exhausted:=true;
    2075   until Exhausted;
     2281        Exhausted := True;
     2282    until Exhausted;
    20762283  end;
    20772284end; // Patrol
     
    20792286procedure TAI.AttackAndPatrol;
    20802287const
    2081 nAttackCatOrder=3;
    2082 AttackCatOrder: array[0..nAttackCatOrder-1] of integer=
    2083 (mctGroundAttacker, mctCruiser, mctGroundDefender);
     2288  nAttackCatOrder = 3;
     2289  AttackCatOrder: array[0..nAttackCatOrder - 1] of integer =
     2290    (mctGroundAttacker, mctCruiser, mctGroundDefender);
    20842291var
    2085 iCat,uix,uix1: integer;
    2086 IsPatrolUnit,Fortified: boolean;
     2292  iCat, uix, uix1: integer;
     2293  IsPatrolUnit, Fortified: boolean;
    20872294begin
    2088 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do // utilize militia
    2089   if (Loc>=0) and (mix=mixMilitia)
    2090     and ((Formation[Loc]<0) or (Formation[Loc]>=maxCOD)
    2091       or (ContinentPresence[Formation[Loc]] and PresenceUnknown=0)) then
    2092     Unit_Disband(uix);
    2093 
    2094 if RO.nEnemyUn>0 then
    2095   for iCat:=0 to nAttackCatOrder-1 do
    2096     for Fortified:=false to true do
    2097       for uix:=RO.nUn-1 downto 0 do with MyUnit[uix] do
    2098         if (Loc>=0) and (ModelCat[mix]=AttackCatOrder[iCat])
    2099           and (MyModel[mix].Attack>0)
    2100           and ((Flags and unFortified<>0) = Fortified) then
    2101           CheckAttack(uix);
    2102 
    2103 fillchar(uixPatrol, sizeof(uixPatrol), $FF);
    2104 for uix:=0 to RO.nUn-1 do with MyUnit[uix],MyModel[mix] do
    2105   if (Loc>=0) and (Domain=dGround) and (Attack>0) and (Speed>=250)
    2106     and (Map[Loc] and fTerrain>=fGrass)
    2107     and (Formation[Loc]>=0) and (Formation[Loc]<maxCOD)
    2108     and ((uixPatrol[Formation[Loc]]<0)
    2109       or (MyUnit[uix].ID<MyUnit[uixPatrol[Formation[Loc]]].ID)) then
    2110       uixPatrol[Formation[Loc]]:=uix;
    2111 
    2112 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do if Loc>=0 then
    2113   begin
    2114   if mix=mixMilitia then
    2115     if (RO.nUn<3) and (RO.nCity=1) or (Map[Loc] and fCity=0) then
    2116       IsPatrolUnit:=true
    2117     else
    2118       begin // militia
    2119       IsPatrolUnit:=false;
    2120       for uix1:=0 to RO.nUn-1 do
    2121         if (uix1<>uix) and (MyUnit[uix1].Loc=Loc)
    2122           and (MyUnit[uix1].mix<>mixSettlers) then
    2123           IsPatrolUnit:=true
    2124       end
    2125   else IsPatrolUnit:=(mix=mixCruiser)
    2126     or (Map[Loc] and fTerrain>=fGrass)
    2127     and (Formation[Loc]>=0) and (Formation[Loc]<maxCOD)
    2128     and (uix=uixPatrol[Formation[Loc]]);
    2129   if IsPatrolUnit then Patrol(uix);
    2130   end
     2295  for uix := 0 to RO.nUn - 1 do
     2296    with MyUnit[uix] do // utilize militia
     2297      if (Loc >= 0) and (mix = mixMilitia) and
     2298        ((Formation[Loc] < 0) or (Formation[Loc] >= maxCOD) or
     2299        (ContinentPresence[Formation[Loc]] and PresenceUnknown = 0)) then
     2300        Unit_Disband(uix);
     2301
     2302  if RO.nEnemyUn > 0 then
     2303    for iCat := 0 to nAttackCatOrder - 1 do
     2304      for Fortified := False to True do
     2305        for uix := RO.nUn - 1 downto 0 do
     2306          with MyUnit[uix] do
     2307            if (Loc >= 0) and (ModelCat[mix] = AttackCatOrder[iCat]) and
     2308              (MyModel[mix].Attack > 0) and ((Flags and unFortified <> 0) =
     2309              Fortified) then
     2310              CheckAttack(uix);
     2311
     2312  fillchar(uixPatrol, sizeof(uixPatrol), $FF);
     2313  for uix := 0 to RO.nUn - 1 do
     2314    with MyUnit[uix], MyModel[mix] do
     2315      if (Loc >= 0) and (Domain = dGround) and (Attack > 0) and
     2316        (Speed >= 250) and (Map[Loc] and fTerrain >= fGrass) and
     2317        (Formation[Loc] >= 0) and (Formation[Loc] < maxCOD) and
     2318        ((uixPatrol[Formation[Loc]] < 0) or (MyUnit[uix].ID <
     2319        MyUnit[uixPatrol[Formation[Loc]]].ID)) then
     2320        uixPatrol[Formation[Loc]] := uix;
     2321
     2322  for uix := 0 to RO.nUn - 1 do
     2323    with MyUnit[uix] do
     2324      if Loc >= 0 then
     2325      begin
     2326        if mix = mixMilitia then
     2327          if (RO.nUn < 3) and (RO.nCity = 1) or (Map[Loc] and fCity = 0) then
     2328            IsPatrolUnit := True
     2329          else
     2330          begin // militia
     2331            IsPatrolUnit := False;
     2332            for uix1 := 0 to RO.nUn - 1 do
     2333              if (uix1 <> uix) and (MyUnit[uix1].Loc = Loc) and
     2334                (MyUnit[uix1].mix <> mixSettlers) then
     2335                IsPatrolUnit := True;
     2336          end
     2337        else
     2338          IsPatrolUnit := (mix = mixCruiser) or (Map[Loc] and fTerrain >= fGrass) and
     2339            (Formation[Loc] >= 0) and (Formation[Loc] < maxCOD) and
     2340            (uix = uixPatrol[Formation[Loc]]);
     2341        if IsPatrolUnit then
     2342          Patrol(uix);
     2343      end;
    21312344end; // AttackAndPatrol
    21322345
     
    21342347function TAI.HavePort: boolean;
    21352348var
    2136 V8, cix,AdjacentLoc,f: integer;
    2137 Adjacent: TVicinity8Loc;
     2349  V8, cix, AdjacentLoc, f: integer;
     2350  Adjacent: TVicinity8Loc;
    21382351begin
    2139 result:=false;
    2140 for cix:=0 to RO.nCity-1 do with MyCity[cix] do if Loc>=0 then
    2141   begin
    2142   V8_to_Loc(Loc,Adjacent);
    2143   for V8:=0 to 7 do
    2144     begin
    2145     AdjacentLoc:=Adjacent[V8];
    2146     if (AdjacentLoc>=0) and ((Map[AdjacentLoc] and fTerrain)<fGrass) then
    2147       begin
    2148       f:=Formation[AdjacentLoc];
    2149       if (f>=0) and (f<maxCOD) and (OceanPresence[f] and not (1 shl me)<>0) then
    2150         result:=true;
    2151       end
    2152     end;
    2153   end
     2352  Result := False;
     2353  for cix := 0 to RO.nCity - 1 do
     2354    with MyCity[cix] do
     2355      if Loc >= 0 then
     2356      begin
     2357        V8_to_Loc(Loc, Adjacent);
     2358        for V8 := 0 to 7 do
     2359        begin
     2360          AdjacentLoc := Adjacent[V8];
     2361          if (AdjacentLoc >= 0) and ((Map[AdjacentLoc] and fTerrain) < fGrass) then
     2362          begin
     2363            f := Formation[AdjacentLoc];
     2364            if (f >= 0) and (f < maxCOD) and (OceanPresence[f] and
     2365              not (1 shl me) <> 0) then
     2366              Result := True;
     2367          end;
     2368        end;
     2369      end;
    21542370end;
    21552371
     
    21572373procedure TAI.SetCityProduction;
    21582374var
    2159 uix,cix,iix,dtr,V8,V21,NewImprovement,AdjacentLoc,MaxSettlers,
    2160   maxcount,cixMilAcademy: integer;
    2161 TerrType: cardinal;
    2162 IsPort,IsNavalBase,NeedCruiser,CheckProd,Destructed,ProduceSettlers,ProduceMil: boolean;
    2163 Adjacent: TVicinity8Loc;
    2164 Radius: TVicinity21Loc;
    2165 Report: TCityReport;
    2166 HomeCount, CityProdRep: array[0..nCmax-1] of integer;
    2167 MilProdCity: array[0..nCmax-1] of boolean;
     2375  uix, cix, iix, dtr, V8, V21, NewImprovement, AdjacentLoc, MaxSettlers,
     2376  maxcount, cixMilAcademy: integer;
     2377  TerrType: cardinal;
     2378  IsPort, IsNavalBase, NeedCruiser, CheckProd, Destructed, ProduceSettlers,
     2379  ProduceMil: boolean;
     2380  Adjacent: TVicinity8Loc;
     2381  Radius: TVicinity21Loc;
     2382  Report: TCityReport;
     2383  HomeCount, CityProdRep: array[0..nCmax - 1] of integer;
     2384  MilProdCity: array[0..nCmax - 1] of boolean;
    21682385
    21692386  procedure TryBuild(Improvement: integer);
    21702387  begin
    2171   if (NewImprovement=imTrGoods) // not already improvement of higher priority found
    2172     and (MyCity[cix].Built[Improvement]=0) // not built yet
    2173     and ((Imp[Improvement].Preq=preNone)
    2174       or (RO.Tech[Imp[Improvement].Preq]>=tsApplicable))
    2175     and City_Improvable(cix, Improvement) then
    2176     NewImprovement:=Improvement;
     2388    if (NewImprovement = imTrGoods) // not already improvement of higher priority found
     2389      and (MyCity[cix].Built[Improvement] = 0) // not built yet
     2390      and ((Imp[Improvement].Preq = preNone) or
     2391      (RO.Tech[Imp[Improvement].Preq] >= tsApplicable)) and
     2392      City_Improvable(cix, Improvement) then
     2393      NewImprovement := Improvement;
    21772394  end;
    21782395
    21792396  procedure TryDestruct(Improvement: integer);
    21802397  begin
    2181   if Destructed or (MyCity[cix].Built[Improvement]=0) then exit;
    2182   if City_CurrentImprovementProject(cix)>=0 then
    2183     City_RebuildImprovement(cix,Improvement)
    2184   else City_SellImprovement(cix, Improvement);
     2398    if Destructed or (MyCity[cix].Built[Improvement] = 0) then
     2399      exit;
     2400    if City_CurrentImprovementProject(cix) >= 0 then
     2401      City_RebuildImprovement(cix, Improvement)
     2402    else
     2403      City_SellImprovement(cix, Improvement);
    21852404{    if (CurrentImprovementProject>=0)
    21862405      and (Imp[CurrentImprovementProject].Kind in [ikCommon,ikNatGlobal,ikNatLocal])
    21872406      and ((Imp[CurrentImprovementProject].Cost*3-Imp[Improvement].Cost*2)
    21882407      *BuildCostMod[G.Difficulty[me]]>MyCity[cix].Prod*(12*3)) then}
    2189   Destructed:=true
     2408    Destructed := True;
    21902409  end;
    21912410
    21922411  function ChooseBuildModel(Cat: integer): integer;
    21932412  var
    2194   count, mix: integer;
    2195   begin
    2196   count:=0;
    2197   for mix:=0 to RO.nModel-1 do
    2198     if (ModelCat[mix]=Cat)
    2199       and (ModelQuality[mix]>=ModelBestQuality[Cat]-MaxBuildWorseThanBestModel) then
    2200       begin inc(count); if random(count)=0 then result:=mix end;
    2201   assert(count>0);
     2413    Count, mix: integer;
     2414  begin
     2415    Count := 0;
     2416    for mix := 0 to RO.nModel - 1 do
     2417      if (ModelCat[mix] = Cat) and (ModelQuality[mix] >=
     2418        ModelBestQuality[Cat] - MaxBuildWorseThanBestModel) then
     2419      begin
     2420        Inc(Count);
     2421        if random(Count) = 0 then
     2422          Result := mix;
     2423      end;
     2424    assert(Count > 0);
    22022425  end;
    22032426
     
    22052428  // find military production cities
    22062429  var
    2207   cix, Total, d, Threshold, NewThreshold, Share, SharePlus, cixWorst: integer;
    2208   begin
    2209   fillchar(MilProdCity, RO.nCity, 0);
    2210   GetCityProdPotential;
    2211   for d:=0 to maxCOD-1 do
    2212     begin
    2213     Total:=0;
    2214     for cix:=0 to RO.nCity-1 do with MyCity[cix] do
    2215       if (Loc>=0) and (District[Loc]=d) then
    2216         Total:=Total+CityResult[cix];
    2217     if Total=0 then continue; // district does not exist
    2218 
    2219     Share:=0;
    2220     cixWorst:=-1;
    2221     for cix:=0 to RO.nCity-1 do with MyCity[cix] do
    2222       if (Loc>=0) and (District[Loc]=d)
    2223         and (Built[imBarracks]+Built[imMilAcademy]>0) then
    2224         begin
    2225         MilProdCity[cix]:=true;
    2226         inc(Share,CityResult[cix]);
    2227         if (cixWorst<0) or (CityResult[cix]<CityResult[cixWorst]) then
    2228           cixWorst:=cix
    2229         end;
    2230 
    2231     Threshold:=$FFFF;
    2232     while (Threshold>0) and (Share<Total*MilProdShare div 100) do
    2233       begin
    2234       NewThreshold:=-1;
    2235       for cix:=0 to RO.nCity-1 do with MyCity[cix] do
    2236         if (Loc>=0) and (District[Loc]=d)
    2237           and (Built[imBarracks]+Built[imMilAcademy]=0) and (Built[imObservatory]=0)
    2238           and (CityResult[cix]<Threshold)
    2239           and (CityResult[cix]>=NewThreshold) then
    2240           if CityResult[cix]>NewThreshold then
    2241             begin
    2242             NewThreshold:=CityResult[cix];
    2243             SharePlus:=CityResult[cix]
    2244             end
    2245           else inc(SharePlus,CityResult[cix]);
    2246       Threshold:=NewThreshold;
    2247       inc(Share,SharePlus);
    2248       end;
    2249 
    2250     for cix:=0 to RO.nCity-1 do with MyCity[cix] do
    2251       if (Loc>=0) and (District[Loc]=d)
    2252         and (Built[imBarracks]+Built[imMilAcademy]=0)
    2253         and (CityResult[cix]>=Threshold) then
    2254         MilProdCity[cix]:=true;
     2430    cix, Total, d, Threshold, NewThreshold, Share, SharePlus, cixWorst: integer;
     2431  begin
     2432    fillchar(MilProdCity, RO.nCity, 0);
     2433    GetCityProdPotential;
     2434    for d := 0 to maxCOD - 1 do
     2435    begin
     2436      Total := 0;
     2437      for cix := 0 to RO.nCity - 1 do
     2438        with MyCity[cix] do
     2439          if (Loc >= 0) and (District[Loc] = d) then
     2440            Total := Total + CityResult[cix];
     2441      if Total = 0 then
     2442        continue; // district does not exist
     2443
     2444      Share := 0;
     2445      cixWorst := -1;
     2446      for cix := 0 to RO.nCity - 1 do
     2447        with MyCity[cix] do
     2448          if (Loc >= 0) and (District[Loc] = d) and
     2449            (Built[imBarracks] + Built[imMilAcademy] > 0) then
     2450          begin
     2451            MilProdCity[cix] := True;
     2452            Inc(Share, CityResult[cix]);
     2453            if (cixWorst < 0) or (CityResult[cix] < CityResult[cixWorst]) then
     2454              cixWorst := cix;
     2455          end;
     2456
     2457      Threshold := $FFFF;
     2458      while (Threshold > 0) and (Share < Total * MilProdShare div 100) do
     2459      begin
     2460        NewThreshold := -1;
     2461        for cix := 0 to RO.nCity - 1 do
     2462          with MyCity[cix] do
     2463            if (Loc >= 0) and (District[Loc] = d) and
     2464              (Built[imBarracks] + Built[imMilAcademy] = 0) and
     2465              (Built[imObservatory] = 0) and (CityResult[cix] < Threshold) and
     2466              (CityResult[cix] >= NewThreshold) then
     2467              if CityResult[cix] > NewThreshold then
     2468              begin
     2469                NewThreshold := CityResult[cix];
     2470                SharePlus := CityResult[cix];
     2471              end
     2472              else
     2473                Inc(SharePlus, CityResult[cix]);
     2474        Threshold := NewThreshold;
     2475        Inc(Share, SharePlus);
     2476      end;
     2477
     2478      for cix := 0 to RO.nCity - 1 do
     2479        with MyCity[cix] do
     2480          if (Loc >= 0) and (District[Loc] = d) and
     2481            (Built[imBarracks] + Built[imMilAcademy] = 0) and
     2482            (CityResult[cix] >= Threshold) then
     2483            MilProdCity[cix] := True;
    22552484{    if (cixWorst>=0)
    22562485      and (Share-CityResult[cixWorst]*2>=Total*MilProdShare div 100) then
     
    22582487    end;
    22592488
    2260   // check best city for military academy
    2261   cixMilAcademy:=cixStateImp[imMilAcademy];
    2262   if cixStateImp[imPalace]>=0 then
    2263     begin
    2264     d:=District[MyCity[cixStateImp[imPalace]].Loc];
    2265     if (d>=0) and (d<maxCOD) then
    2266       begin
    2267       cixMilAcademy:=-1;
    2268       for cix:=0 to RO.nCity-1 do with MyCity[cix] do
    2269         if (Loc>=0) and (District[Loc]=d)
    2270           and (Built[imObservatory]+Built[imPalace]=0)
    2271           and ((cixMilAcademy<0) or (CityResult[cix]>CityResult[cixMilAcademy])) then
    2272           cixMilAcademy:=cix;
    2273       end;
    2274     if (cixMilAcademy>=0) and (cixStateImp[imMilAcademy]>=0)
    2275       and (cixMilAcademy<>cixStateImp[imMilAcademy])
    2276       and (MyCity[cixStateImp[imMilAcademy]].Built[imObservatory]=0)
    2277       and (CityResult[cixMilAcademy]<=CityResult[cixStateImp[imMilAcademy]]*3 div 2) then
    2278       cixMilAcademy:=cixStateImp[imMilAcademy] // because not so much better
    2279     end
     2489    // check best city for military academy
     2490    cixMilAcademy := cixStateImp[imMilAcademy];
     2491    if cixStateImp[imPalace] >= 0 then
     2492    begin
     2493      d := District[MyCity[cixStateImp[imPalace]].Loc];
     2494      if (d >= 0) and (d < maxCOD) then
     2495      begin
     2496        cixMilAcademy := -1;
     2497        for cix := 0 to RO.nCity - 1 do
     2498          with MyCity[cix] do
     2499            if (Loc >= 0) and (District[Loc] = d) and
     2500              (Built[imObservatory] + Built[imPalace] = 0) and
     2501              ((cixMilAcademy < 0) or (CityResult[cix] > CityResult[cixMilAcademy])) then
     2502              cixMilAcademy := cix;
     2503      end;
     2504      if (cixMilAcademy >= 0) and (cixStateImp[imMilAcademy] >= 0) and
     2505        (cixMilAcademy <> cixStateImp[imMilAcademy]) and
     2506        (MyCity[cixStateImp[imMilAcademy]].Built[imObservatory] = 0) and
     2507        (CityResult[cixMilAcademy] <= CityResult[cixStateImp[imMilAcademy]] *
     2508        3 div 2) then
     2509        cixMilAcademy := cixStateImp[imMilAcademy]; // because not so much better
     2510    end;
    22802511  end;
    22812512
    22822513  procedure ChangeHomeCities;
    22832514  var
    2284   uix,NewHome,HomeSupport,NewHomeSupport,SingleSupport: integer;
    2285   begin
    2286   if RO.Government in [gAnarchy, gFundamentalism] then exit;
    2287   for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    2288     if (Loc>=0) and (Home>=0) and (Map[Loc] and fCity<>0)
    2289       and (MyCity[Home].Loc<>Loc) and (MyModel[mix].Kind<>mkSettler) then
    2290       begin
    2291       City_FindMyCity(Loc, NewHome);
    2292       case RO.Government of
    2293         gDespotism:
     2515    uix, NewHome, HomeSupport, NewHomeSupport, SingleSupport: integer;
     2516  begin
     2517    if RO.Government in [gAnarchy, gFundamentalism] then
     2518      exit;
     2519    for uix := 0 to RO.nUn - 1 do
     2520      with MyUnit[uix] do
     2521        if (Loc >= 0) and (Home >= 0) and (Map[Loc] and fCity <> 0) and
     2522          (MyCity[Home].Loc <> Loc) and (MyModel[mix].Kind <> mkSettler) then
     2523        begin
     2524          City_FindMyCity(Loc, NewHome);
     2525          case RO.Government of
     2526            gDespotism:
     2527            begin
     2528              HomeSupport := HomeCount[Home] - MyCity[Home].Size;
     2529              NewHomeSupport := HomeCount[NewHome] - MyCity[NewHome].Size;
     2530            end;
     2531            gMonarchy, gCommunism:
     2532            begin
     2533              HomeSupport := HomeCount[Home] - MyCity[Home].Size div 2;
     2534              NewHomeSupport := HomeCount[NewHome] - MyCity[NewHome].Size div 2;
     2535            end;
     2536            else
     2537            begin
     2538              HomeSupport := HomeCount[Home];
     2539              NewHomeSupport := HomeCount[NewHome];
     2540            end;
     2541          end;
     2542          if HomeSupport > 0 then
    22942543          begin
    2295           HomeSupport:=HomeCount[Home]-MyCity[Home].Size;
    2296           NewHomeSupport:=HomeCount[NewHome]-MyCity[NewHome].Size;
     2544            if MyModel[mix].Flags and mdDoubleSupport = 0 then
     2545              SingleSupport := 1
     2546            else
     2547              SingleSupport := 2;
     2548            HomeSupport := HomeSupport - SingleSupport;
     2549            NewHomeSupport := NewHomeSupport + SingleSupport;
     2550            if HomeSupport < 0 then
     2551              HomeSupport := 0;
     2552            if NewHomeSupport < 0 then
     2553              NewHomeSupport := 0;
     2554            if (NewHomeSupport <= 0) or (CityProdRep[Home] -
     2555              HomeSupport <= CityProdRep[NewHome] - NewHomeSupport) then
     2556            begin
     2557              Dec(HomeCount[Home], SingleSupport);
     2558              Inc(HomeCount[NewHome], SingleSupport);
     2559              Unit_SetHomeHere(uix);
     2560            end;
    22972561          end;
    2298         gMonarchy, gCommunism:
     2562        end;
     2563  end;
     2564
     2565begin
     2566  fillchar(HomeCount, 4 * RO.nCity, 0);
     2567  for uix := 0 to RO.nUn - 1 do
     2568    with MyUnit[uix] do
     2569      if (Loc >= 0) and (Home >= 0) then
     2570        if MyModel[mix].Flags and mdDoubleSupport = 0 then
     2571          Inc(HomeCount[Home])
     2572        else
     2573          Inc(HomeCount[Home], 2);
     2574
     2575  NominateMilProdCities;
     2576
     2577  for cix := 0 to RO.nCity - 1 do
     2578    with MyCity[cix] do
     2579      if (Loc >= 0) and (Flags and chCaptured = 0) and (District[Loc] >= 0) then
     2580      begin
     2581        if size < 4 then
     2582          City_OptimizeTiles(cix, rwMaxGrowth)
     2583        else
     2584          City_OptimizeTiles(cix, rwForceProd);
     2585
     2586        City_GetReport(cix, Report);
     2587        CityProdRep[cix] := Report.ProdRep;
     2588
     2589        Destructed := False;
     2590        CheckProd := (RO.Turn = 0) or ((Flags and chProduction) <>
     2591          0) // city production complete
     2592          or not City_HasProject(cix);
     2593        if not CheckProd then
     2594        begin // check whether producing double state improvement or wonder
     2595          iix := City_CurrentImprovementProject(cix);
     2596          if (iix >= 0) and (((Imp[iix].Kind in [ikNatLocal, ikNatGlobal]) and
     2597            (RO.NatBuilt[iix] > 0)) or ((Imp[iix].Kind = ikWonder) and
     2598            (RO.Wonder[iix].CityID <> -1))) then
     2599            CheckProd := True;
     2600        end;
     2601        if CheckProd then
     2602        begin // check production
     2603          IsPort := False;
     2604          IsNavalBase := False;
     2605          NeedCruiser := False;
     2606          V8_to_Loc(Loc, Adjacent);
     2607          for V8 := 0 to 7 do
    22992608          begin
    2300           HomeSupport:=HomeCount[Home]-MyCity[Home].Size div 2;
    2301           NewHomeSupport:=HomeCount[NewHome]-MyCity[NewHome].Size div 2;
     2609            AdjacentLoc := Adjacent[V8];
     2610            if (AdjacentLoc >= 0) and ((Map[AdjacentLoc] and fTerrain) < fGrass) then
     2611            begin
     2612              IsPort := True; // shore tile at adjacent location -- city is port!
     2613              if (Formation[AdjacentLoc] >= 0) and
     2614                (Formation[AdjacentLoc] < maxCOD) and
     2615                (OceanPresence[Formation[AdjacentLoc]] and WarNations <> 0) then
     2616              begin
     2617                IsNavalBase := True;
     2618                if (1 shl Formation[AdjacentLoc]) and OceanWithShip = 0 then
     2619                  NeedCruiser := True;
     2620              end;
     2621            end;
    23022622          end;
    2303         else
     2623
     2624          if RO.Turn = 0 then
    23042625          begin
    2305           HomeSupport:=HomeCount[Home];
    2306           NewHomeSupport:=HomeCount[NewHome];
     2626            NewImprovement := -1;
     2627            City_StartUnitProduction(cix, mixMilitia); // militia
     2628          end
     2629          else
     2630            NewImprovement := imTrGoods;
     2631
     2632          dtr := District[Loc]; // formation of city
     2633
     2634          if NewImprovement = imTrGoods then
     2635          begin
     2636            if (Built[imPalace] + Built[imCourt] + Built[imTownHall] = 0) then
     2637              TryBuild(imTownHall);
    23072638          end;
    2308         end;
    2309       if HomeSupport>0 then
    2310         begin
    2311         if MyModel[mix].Flags and mdDoubleSupport=0 then SingleSupport:=1
    2312         else SingleSupport:=2;
    2313         HomeSupport:=HomeSupport-SingleSupport;
    2314         NewHomeSupport:=NewHomeSupport+SingleSupport;
    2315         if HomeSupport<0 then HomeSupport:=0;
    2316         if NewHomeSupport<0 then NewHomeSupport:=0;
    2317         if (NewHomeSupport<=0)
    2318           or (CityProdRep[Home]-HomeSupport<=CityProdRep[NewHome]-NewHomeSupport) then
     2639
     2640          if (NewImprovement = imTrGoods) and (RO.Government = gDespotism) and
     2641            (Report.Support = 0) then
     2642          begin // produce town guard
     2643            NewImprovement := -1;
     2644            City_StartUnitProduction(cix, mixTownGuard);
     2645          end;
     2646
     2647          if NewImprovement = imTrGoods then
    23192648          begin
    2320           dec(HomeCount[Home],SingleSupport);
    2321           inc(HomeCount[NewHome],SingleSupport);
    2322           Unit_SetHomeHere(uix)
    2323           end
    2324         end
    2325       end
    2326   end;
    2327 
    2328 begin
    2329 fillchar(HomeCount, 4*RO.nCity, 0);
    2330 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do
    2331   if (Loc>=0) and (Home>=0) then
    2332     if MyModel[mix].Flags and mdDoubleSupport=0 then
    2333       inc(HomeCount[Home])
    2334     else inc(HomeCount[Home],2);
    2335 
    2336 NominateMilProdCities;
    2337 
    2338 for cix:=0 to RO.nCity-1 do with MyCity[cix] do
    2339   if (Loc>=0) and (Flags and chCaptured=0) and (District[Loc]>=0) then
    2340     begin
    2341     if size<4 then
    2342       City_OptimizeTiles(cix,rwMaxGrowth)
    2343     else City_OptimizeTiles(cix,rwForceProd);
    2344 
    2345     City_GetReport(cix, Report);
    2346     CityProdRep[cix]:=Report.ProdRep;
    2347 
    2348     Destructed:=false;
    2349     CheckProd:= (RO.Turn=0) or ((Flags and chProduction)<>0) // city production complete
    2350       or not City_HasProject(cix);
    2351     if not CheckProd then
    2352       begin // check whether producing double state improvement or wonder
    2353       iix:=City_CurrentImprovementProject(cix);
    2354       if (iix>=0)
    2355         and (((Imp[iix].Kind in [ikNatLocal,ikNatGlobal]) and (RO.NatBuilt[iix]>0))
    2356           or ((Imp[iix].Kind=ikWonder) and (RO.Wonder[iix].CityID<>-1))) then
    2357         CheckProd:=true;
    2358       end;
    2359     if CheckProd then
    2360       begin // check production
    2361       IsPort:=false;
    2362       IsNavalBase:=false;
    2363       NeedCruiser:=false;
    2364       V8_to_Loc(Loc,Adjacent);
    2365       for V8:=0 to 7 do
    2366         begin
    2367         AdjacentLoc:=Adjacent[V8];
    2368         if (AdjacentLoc>=0) and ((Map[AdjacentLoc] and fTerrain)<fGrass) then
     2649            if RO.Government = gDespotism then
     2650              maxcount := Size
     2651            else
     2652              maxcount := Size div 2;
     2653
     2654            if IsResearched(adRailroad) and (mixSettlers =
     2655              0) // better wait for engineers
     2656              or (Built[imColosseum] + Built[imObservatory] > 0) then
     2657              MaxSettlers := 1
     2658            else
     2659              MaxSettlers := (Size + 2) div 6;
     2660            ProduceSettlers :=
     2661              (HomeCount[cix] < maxcount + Size div 2) and
     2662              ((Report.Eaten - Size * 2) div SettlerFood[RO.Government] <
     2663              MaxSettlers) and ((dtr < 0) or (dtr >= maxCOD) or
     2664              (SettlerSurplus[dtr] <= 0));
     2665
     2666            ProduceMil := (HomeCount[cix] < maxcount + Size div 2) and
     2667              (Built[imBarracks] + Built[imMilAcademy] > 0) and
     2668              ((ModelBestQuality[mctGroundDefender] > 0) or
     2669              (ModelBestQuality[mctGroundAttacker] > 0)) and
     2670              ((dtr < maxCOD) and ((UnitLack[dtr, mctGroundAttacker] > 0) or
     2671              (UnitLack[dtr, mctGroundDefender] > 0)) or (HomeCount[cix] < maxcount));
     2672
     2673            if ProduceMil or not ProduceSettlers and (HomeCount[cix] < maxcount) then
     2674            begin
     2675              NewImprovement := -1;
     2676              if (dtr >= maxCOD) or
     2677                (ModelBestQuality[mctGroundDefender] = 0) or
     2678                (UnitLack[dtr, mctGroundAttacker] >=
     2679                UnitLack[dtr, mctGroundDefender]) then
     2680                City_StartUnitProduction(cix, ChooseBuildModel(mctGroundAttacker))
     2681              else
     2682                City_StartUnitProduction(cix, ChooseBuildModel(mctGroundDefender));
     2683            end
     2684            else if ProduceSettlers then
     2685            begin
     2686              NewImprovement := -1;
     2687              City_StartUnitProduction(cix, mixSettlers);
     2688            end;
     2689          end;
     2690
     2691          if NewImprovement >= 0 then
     2692          begin // produce improvement
     2693            if (RO.Turn >= 40) and (Report.Happy * 2 <= Size) and
     2694              (Built[imColosseum] = 0) then
     2695              TryBuild(imTemple);
     2696            if cix = cixMilAcademy then
     2697              TryBuild(imMilAcademy)
     2698            else if ((Built[imPalace] > 0) or MilProdCity[cix] and
     2699              (Built[imTemple] > 0)) and (Built[imObservatory] = 0) then
     2700              TryBuild(imBarracks);
     2701            if Report.Trade - Report.Corruption >= 11 then
     2702              TryBuild(imLibrary);
     2703            if Report.Trade - Report.Corruption >= 11 then
     2704              TryBuild(imMarket);
     2705            if (Report.Trade - Report.Corruption >= 11) and (Report.Happy >= 4) then
     2706              TryBuild(imUniversity);
     2707            if (Built[imPalace] > 0) and (Report.Trade - Report.Corruption >= 11) and
     2708              (Report.Happy >= 4) and (RO.NatBuilt[imObservatory] = 0) then
     2709              TryBuild(imObservatory); // always build observatory in capital
     2710            if (Report.Trade - Report.Corruption >= 15) and (Report.Happy >= 4) then
     2711              TryBuild(imResLab);
     2712            if (Size >= 9) and (Built[imPalace] + Built[imCourt] > 0) then
     2713              TryBuild(imHighways);
     2714            if (RO.Government <> gDespotism) and (Report.Happy * 2 <= Size) and
     2715              (Built[imCathedral] + Built[imTheater] + Built[imColosseum] = 0) then
     2716            begin
     2717              TryBuild(imCathedral);
     2718              TryBuild(imTheater);
     2719            end;
     2720            if (RO.Government <> gDespotism) and (Size >= NeedAqueductSize) then
     2721              TryBuild(imAqueduct);
     2722            if (Built[imColosseum] + Built[imObservatory] > 0) and
     2723              (Size >= NeedSewerSize) then
     2724              TryBuild(imSewer);
     2725            if (RO.NatBuilt[imGrWall] = 0) and
     2726              (Built[imObservatory] + Built[imMilAcademy] = 0) and
     2727              (RO.nCity >= 6) and (cixStateImp[imPalace] >= 0) and
     2728              (Formation[Loc] = Formation[MyCity[cixStateImp[imPalace]].Loc]) and
     2729              (Report.ProdRep - Report.Support >= 6) then
     2730              TryBuild(imGrWall);
     2731            //        if Map[Loc] and fGrWall=0 then
     2732            //          TryBuild(imWalls);
     2733            //        if IsNavalBase then
     2734            //          TryBuild(imCoastalFort);
     2735            if (RO.NatBuilt[imSpacePort] = 0) and
     2736              (Built[imObservatory] + Built[imMilAcademy] = 0) and
     2737              (Report.ProdRep - Report.Support >= 10) then
     2738              TryBuild(imSpacePort);
     2739            if Report.ProdRep >= 8 then
     2740              TryBuild(imFactory);
     2741            if Report.ProdRep >= 12 then
     2742              TryBuild(imMfgPlant);
     2743            if IsPort then
     2744              if Size > 8 then
     2745                TryBuild(imHarbor)
     2746              else if (Built[imHarbor] = 0) and (Size > 4) and
     2747                ((Size and 1 <> 0) and (Report.Happy * 2 > Size) or
     2748                (Built[imColosseum] > 0)) then
     2749              begin // check building harbor
     2750                V21_to_Loc(Loc, Radius);
     2751                for V21 := 1 to 26 do // city is in growth mode - using any 1-food tile?
     2752                  if Tiles and (1 shl V21) <> 0 then
     2753                  begin
     2754                    TerrType := Map[Radius[V21]] and (fTerrain or fSpecial);
     2755                    if TerrType in [fDesert, fTundra, fSwamp, fForest,
     2756                      fHills, fMountains] then
     2757                    begin
     2758                      TryBuild(imHarbor);
     2759                      break;
     2760                    end;
     2761                  end;
     2762              end;
     2763            if (Size <= 10) and (Report.FoodRep - Report.Eaten < 2) and
     2764              (Report.Happy * 2 >= Size + 2) then
     2765              TryBuild(imSuperMarket);
     2766
     2767            // less important
     2768            if (Built[imPalace] > 0) and (RO.NatBuilt[imColosseum] = 0) and
     2769              (Size >= 10) then
     2770              TryBuild(imColosseum); // always build colosseum in capital
     2771            if (Built[imPalace] + Built[imCourt] = 0) and
     2772              ((Report.Corruption > 2) or IsResearched(Imp[imHighways].Preq)) then
     2773              TryBuild(imCourt); // replace courthouse
     2774            if Report.PollRep >= 15 then
     2775              TryBuild(imRecycling);
     2776            if (Report.Trade - Report.Corruption >= 11) and
     2777              (RO.Money < TotalPopulation[me] * 2) then
     2778              TryBuild(imBank);
     2779            if (RO.NatBuilt[imStockEx] = 0) and
     2780              (Built[imObservatory] + Built[imMilAcademy] = 0) and
     2781              (Report.ProdRep - Report.Support >= 8) then
     2782              TryBuild(imStockEx);
     2783
     2784            // every improvement checked -- start production now
     2785            if NewImprovement <> imTrGoods then
     2786            begin
     2787              if City_StartImprovement(cix, NewImprovement) < rExecuted then
     2788                NewImprovement := imTrGoods;
     2789            end;
     2790            if (NewImprovement = imTrGoods) and (RO.Turn and $F = 0) then
     2791            begin // try colony ship parts
     2792              NewImprovement := imShipComp;
     2793              while (NewImprovement <= imShipHab) and
     2794                ((RO.Tech[Imp[NewImprovement].Preq] < 0) or
     2795                  (City_StartImprovement(cix, NewImprovement) < rExecuted)) do
     2796                Inc(NewImprovement);
     2797              if NewImprovement > imShipHab then
     2798                NewImprovement := imTrGoods;
     2799            end;
     2800          end;
     2801
     2802          if (NewImprovement = imTrGoods) and NeedCruiser and
     2803            (mixCruiser >= 0) and (Project and (cpImp or cpIndex) <> mixCruiser) and
     2804            (Report.ProdRep - Report.Support >= 6) then
    23692805          begin
    2370           IsPort:=true; // shore tile at adjacent location -- city is port!
    2371           if (Formation[AdjacentLoc]>=0) and (Formation[AdjacentLoc]<maxCOD)
    2372             and (OceanPresence[Formation[AdjacentLoc]] and WarNations<>0) then
    2373             begin
    2374             IsNavalBase:=true;
    2375             if (1 shl Formation[AdjacentLoc]) and OceanWithShip=0 then
    2376               NeedCruiser:=true
    2377             end
    2378           end
    2379         end;
    2380 
    2381       if RO.Turn=0 then
    2382         begin
    2383         NewImprovement:=-1;
    2384         City_StartUnitProduction(cix,mixMilitia); // militia
    2385         end
    2386       else NewImprovement:=imTrGoods;
    2387 
    2388       dtr:=District[Loc]; // formation of city
    2389 
    2390       if NewImprovement=imTrGoods then
    2391         begin
    2392         if (Built[imPalace]+Built[imCourt]+Built[imTownHall]=0) then
    2393           TryBuild(imTownHall);
    2394         end;
    2395 
    2396       if (NewImprovement=imTrGoods)
    2397         and (RO.Government=gDespotism) and (Report.Support=0) then
    2398         begin // produce town guard
    2399         NewImprovement:=-1;
    2400         City_StartUnitProduction(cix,mixTownGuard);
    2401         end;
    2402 
    2403       if NewImprovement=imTrGoods then
    2404         begin
    2405         if RO.Government=gDespotism then maxcount:=Size
    2406         else maxcount:=Size div 2;
    2407 
    2408         if IsResearched(adRailroad) and (mixSettlers=0) // better wait for engineers
    2409           or (Built[imColosseum]+Built[imObservatory]>0) then
    2410           MaxSettlers:=1
    2411         else MaxSettlers:=(Size+2) div 6;
    2412         ProduceSettlers:=(HomeCount[cix]<maxcount+Size div 2)
    2413           and ((Report.Eaten-Size*2) div SettlerFood[RO.Government]<MaxSettlers)
    2414           and ((dtr<0) or (dtr>=maxCOD) or (SettlerSurplus[dtr]<=0));
    2415 
    2416         ProduceMil:=(HomeCount[cix]<maxcount+Size div 2)
    2417           and (Built[imBarracks]+Built[imMilAcademy]>0)
    2418           and ((ModelBestQuality[mctGroundDefender]>0)
    2419             or (ModelBestQuality[mctGroundAttacker]>0))
    2420           and ((dtr<maxCOD)
    2421             and ((UnitLack[dtr,mctGroundAttacker]>0)
    2422               or (UnitLack[dtr,mctGroundDefender]>0))
    2423             or (HomeCount[cix]<maxcount));
    2424 
    2425         if ProduceMil or not ProduceSettlers and (HomeCount[cix]<maxcount) then
    2426           begin
    2427           NewImprovement:=-1;
    2428           if (dtr>=maxCOD)
    2429             or (ModelBestQuality[mctGroundDefender]=0)
    2430             or (UnitLack[dtr,mctGroundAttacker]
    2431               >=UnitLack[dtr,mctGroundDefender]) then
    2432             City_StartUnitProduction(cix,ChooseBuildModel(mctGroundAttacker))
    2433           else City_StartUnitProduction(cix,ChooseBuildModel(mctGroundDefender))
    2434           end
    2435         else if ProduceSettlers then
    2436           begin
    2437           NewImprovement:=-1;
    2438           City_StartUnitProduction(cix,mixSettlers);
    2439           end
    2440         end;
    2441 
    2442       if NewImprovement>=0 then
    2443         begin // produce improvement
    2444         if (RO.Turn>=40) and (Report.Happy*2<=Size)
    2445           and (Built[imColosseum]=0) then
    2446           TryBuild(imTemple);
    2447         if cix=cixMilAcademy then
    2448           TryBuild(imMilAcademy)
    2449         else if ((Built[imPalace]>0) or MilProdCity[cix] and (Built[imTemple]>0))
    2450           and (Built[imObservatory]=0) then
    2451           TryBuild(imBarracks);
    2452         if Report.Trade-Report.Corruption>=11 then
    2453           TryBuild(imLibrary);
    2454         if Report.Trade-Report.Corruption>=11 then
    2455           TryBuild(imMarket);
    2456         if (Report.Trade-Report.Corruption>=11) and (Report.Happy>=4) then
    2457           TryBuild(imUniversity);
    2458         if (Built[imPalace]>0) and (Report.Trade-Report.Corruption>=11)
    2459           and (Report.Happy>=4) and (RO.NatBuilt[imObservatory]=0) then
    2460           TryBuild(imObservatory); // always build observatory in capital
    2461         if (Report.Trade-Report.Corruption>=15) and (Report.Happy>=4) then
    2462           TryBuild(imResLab);
    2463         if (Size>=9) and (Built[imPalace]+Built[imCourt]>0) then
    2464           TryBuild(imHighways);
    2465         if (RO.Government<>gDespotism) and (Report.Happy*2<=Size)
    2466           and (Built[imCathedral]+Built[imTheater]+Built[imColosseum]=0) then
    2467           begin
    2468           TryBuild(imCathedral);
    2469           TryBuild(imTheater);
     2806            NewImprovement := -1;
     2807            City_StartUnitProduction(cix, mixCruiser);
    24702808          end;
    2471         if (RO.Government<>gDespotism) and (Size>=NeedAqueductSize) then
    2472           TryBuild(imAqueduct);
    2473         if (Built[imColosseum]+Built[imObservatory]>0) and (Size>=NeedSewerSize) then
    2474           TryBuild(imSewer);
    2475         if (RO.NatBuilt[imGrWall]=0) and (Built[imObservatory]+Built[imMilAcademy]=0)
    2476           and (RO.nCity>=6) and (cixStateImp[imPalace]>=0)
    2477           and (Formation[Loc]=Formation[MyCity[cixStateImp[imPalace]].Loc])
    2478           and (Report.ProdRep-Report.Support>=6) then
    2479           TryBuild(imGrWall);
    2480   //        if Map[Loc] and fGrWall=0 then
    2481   //          TryBuild(imWalls);
    2482   //        if IsNavalBase then
    2483   //          TryBuild(imCoastalFort);
    2484         if (RO.NatBuilt[imSpacePort]=0) and (Built[imObservatory]+Built[imMilAcademy]=0)
    2485           and (Report.ProdRep-Report.Support>=10) then
    2486           TryBuild(imSpacePort);
    2487         if Report.ProdRep>=8 then
    2488           TryBuild(imFactory);
    2489         if Report.ProdRep>=12 then
    2490           TryBuild(imMfgPlant);
    2491         if IsPort then
    2492           if Size>8 then
    2493             TryBuild(imHarbor)
    2494           else if (Built[imHarbor]=0) and (Size>4)
    2495             and ((Size and 1<>0) and (Report.Happy*2>Size)
    2496               or (Built[imColosseum]>0)) then
    2497             begin // check building harbor
    2498             V21_to_Loc(Loc,Radius);
    2499             for V21:=1 to 26 do // city is in growth mode - using any 1-food tile?
    2500               if Tiles and (1 shl V21)<>0 then
    2501                 begin
    2502                 TerrType:=Map[Radius[V21]] and (fTerrain or fSpecial);
    2503                 if TerrType in [fDesert,fTundra,fSwamp,fForest,fHills,fMountains] then
    2504                   begin TryBuild(imHarbor); break end
    2505                 end
    2506             end;
    2507         if (Size<=10) and (Report.FoodRep-Report.Eaten<2) and
    2508           (Report.Happy*2>=Size+2) then
    2509           TryBuild(imSuperMarket);
    2510 
    2511         // less important
    2512         if (Built[imPalace]>0) and (RO.NatBuilt[imColosseum]=0)
    2513           and (Size>=10) then
    2514           TryBuild(imColosseum); // always build colosseum in capital
    2515         if (Built[imPalace]+Built[imCourt]=0)
    2516           and ((Report.Corruption>2) or IsResearched(Imp[imHighways].Preq)) then
    2517           TryBuild(imCourt); // replace courthouse
    2518         if Report.PollRep>=15 then
    2519           TryBuild(imRecycling);
    2520         if (Report.Trade-Report.Corruption>=11)
    2521           and (RO.Money<TotalPopulation[me]*2) then
    2522           TryBuild(imBank);
    2523         if (RO.NatBuilt[imStockEx]=0) and (Built[imObservatory]+Built[imMilAcademy]=0)
    2524           and (Report.ProdRep-Report.Support>=8) then
    2525           TryBuild(imStockEx);
    2526 
    2527         // every improvement checked -- start production now
    2528         if NewImprovement<>imTrGoods then
    2529           begin
    2530           if City_StartImprovement(cix, NewImprovement)<rExecuted then
    2531             NewImprovement:=imTrGoods
    2532           end;
    2533         if (NewImprovement=imTrGoods) and (RO.Turn and $F=0) then
    2534           begin // try colony ship parts
    2535           NewImprovement:=imShipComp;
    2536           while (NewImprovement<=imShipHab)
    2537             and ((RO.Tech[Imp[NewImprovement].Preq]<0)
    2538             or (City_StartImprovement(cix, NewImprovement)<rExecuted)) do
    2539             inc(NewImprovement);
    2540           if NewImprovement>imShipHab then NewImprovement:=imTrGoods
    2541           end
    2542         end;
    2543 
    2544       if (NewImprovement=imTrGoods) and NeedCruiser and (mixCruiser>=0)
    2545         and (Project and (cpImp or cpIndex)<>mixCruiser)
    2546         and (Report.ProdRep-Report.Support>=6) then
    2547         begin
    2548         NewImprovement:=-1;
    2549         City_StartUnitProduction(cix,mixCruiser);
    2550         end;
    2551 
    2552       if (NewImprovement=imTrGoods) and City_HasProject(cix) then
    2553         City_StopProduction(cix);
    2554 
    2555       // rebuild imps no longer needed
    2556       if (RO.TaxRate=0) and (RO.Money>=TotalPopulation[me]*4) then
    2557         TryDestruct(imBank)
    2558       else if Report.Happy*2>=Size+6 then
    2559         TryDestruct(imTheater)
    2560       else if Report.Happy*2>=Size+4 then
    2561         TryDestruct(imTemple)
    2562       end;
    2563 
    2564     // rebuild imps no longer needed, no report needed
    2565     if (Built[imObservatory]>0)
    2566       or (Project and (cpImp or cpIndex)=cpImp or imObservatory)
    2567       {or not MilProdCity[cix]} then
    2568       TryDestruct(imBarracks);
    2569     if Map[Loc] and fGrWall<>0 then
    2570       TryDestruct(imWalls);
    2571     if Built[imColosseum]>0 then
    2572       begin
    2573       TryDestruct(imTheater);
    2574       TryDestruct(imCathedral);
    2575       TryDestruct(imTemple);
    2576       end;
    2577     end;
    2578 
    2579 ChangeHomeCities;
     2809
     2810          if (NewImprovement = imTrGoods) and City_HasProject(cix) then
     2811            City_StopProduction(cix);
     2812
     2813          // rebuild imps no longer needed
     2814          if (RO.TaxRate = 0) and (RO.Money >= TotalPopulation[me] * 4) then
     2815            TryDestruct(imBank)
     2816          else if Report.Happy * 2 >= Size + 6 then
     2817            TryDestruct(imTheater)
     2818          else if Report.Happy * 2 >= Size + 4 then
     2819            TryDestruct(imTemple);
     2820        end;
     2821
     2822        // rebuild imps no longer needed, no report needed
     2823        if (Built[imObservatory] > 0) or (Project and (cpImp or cpIndex) =
     2824          cpImp or imObservatory)
     2825        {or not MilProdCity[cix]} then
     2826          TryDestruct(imBarracks);
     2827        if Map[Loc] and fGrWall <> 0 then
     2828          TryDestruct(imWalls);
     2829        if Built[imColosseum] > 0 then
     2830        begin
     2831          TryDestruct(imTheater);
     2832          TryDestruct(imCathedral);
     2833          TryDestruct(imTemple);
     2834        end;
     2835      end;
     2836
     2837  ChangeHomeCities;
    25802838end; // SetCityProduction
    25812839
     
    25832841function TAI.ChooseGovernment: integer;
    25842842begin
    2585 if Data.BehaviorFlags and bBarbarina<>0 then
    2586   if IsResearched(adTheology) then result:=gFundamentalism
    2587   else result:=gDespotism
    2588 else if IsResearched(adDemocracy) then
    2589   result:=gDemocracy //!!!
    2590 else if IsResearched(adTheRepublic) then
    2591   result:=gRepublic
    2592 else if IsResearched(adMonarchy) then
    2593   result:=gMonarchy
    2594 else result:=gDespotism
     2843  if Data.BehaviorFlags and bBarbarina <> 0 then
     2844    if IsResearched(adTheology) then
     2845      Result := gFundamentalism
     2846    else
     2847      Result := gDespotism
     2848  else if IsResearched(adDemocracy) then
     2849    Result := gDemocracy //!!!
     2850  else if IsResearched(adTheRepublic) then
     2851    Result := gRepublic
     2852  else if IsResearched(adMonarchy) then
     2853    Result := gMonarchy
     2854  else
     2855    Result := gDespotism;
    25952856end;
    25962857
     
    26022863function TAI.MostWanted(Nation, adGiveAway: integer): integer;
    26032864var
    2604 ad: integer;
     2865  ad: integer;
    26052866begin
    2606 result:=-1;
    2607 if RO.Tech[adGiveAway]>=tsApplicable then
    2608   if (adGiveAway=adTheRepublic) and (Data.BehaviorFlags and bGender=bFemale)
    2609     and (RO.Tech[adTheology]<tsSeen) then
    2610     begin
    2611     if RO.EnemyReport[Nation].Tech[adTheology]>=tsApplicable then
    2612       result:=adTheology
     2867  Result := -1;
     2868  if RO.Tech[adGiveAway] >= tsApplicable then
     2869    if (adGiveAway = adTheRepublic) and (Data.BehaviorFlags and bGender = bFemale) and
     2870      (RO.Tech[adTheology] < tsSeen) then
     2871    begin
     2872      if RO.EnemyReport[Nation].Tech[adTheology] >= tsApplicable then
     2873        Result := adTheology;
    26132874    end
    2614   else for ad:=0 to nAdv-5 do // no future techs
    2615       if (AdvanceValue[ad]>0)
    2616         and (RO.Tech[ad]<tsSeen) and (ad<>RO.ResearchTech)
    2617         and (RO.EnemyReport[Nation].Tech[ad]>=tsApplicable)
    2618         and ((Advancedness[adGiveAway]<=Advancedness[ad]+AdvanceValue[ad] shr 8+Compromise)
    2619           or (adGiveAway=adScience) and (Nation=Data.TheologyPartner))
    2620         and ((result<0)
    2621           or ((Advancedness[adGiveAway]+Compromise>=Advancedness[ad]) // acceptable for opponent
    2622             or (ad=adScience))
    2623           and (AdvanceValue[ad]>AdvanceValue[result])
    2624           or (result<>adScience)
    2625           and (Advancedness[adGiveAway]+Compromise<Advancedness[result])
    2626           and (Advancedness[ad]<Advancedness[result]))
    2627         and ((ad<>adTheRepublic) or (Data.BehaviorFlags and bGender=bFemale)
    2628           or (RO.EnemyReport[Nation].Tech[adTheology]>=tsSeen)) then
    2629         result:=ad
     2875    else
     2876      for ad := 0 to nAdv - 5 do // no future techs
     2877        if (AdvanceValue[ad] > 0) and (RO.Tech[ad] < tsSeen) and
     2878          (ad <> RO.ResearchTech) and (RO.EnemyReport[Nation].Tech[ad] >=
     2879          tsApplicable) and ((Advancedness[adGiveAway] <= Advancedness[ad] +
     2880          AdvanceValue[ad] shr 8 + Compromise) or (adGiveAway = adScience) and
     2881          (Nation = Data.TheologyPartner)) and
     2882          ((Result < 0) or ((Advancedness[adGiveAway] + Compromise >=
     2883          Advancedness[ad]) // acceptable for opponent
     2884          or (ad = adScience)) and (AdvanceValue[ad] > AdvanceValue[Result]) or
     2885          (Result <> adScience) and (Advancedness[adGiveAway] +
     2886          Compromise < Advancedness[Result]) and (Advancedness[ad] <
     2887          Advancedness[Result])) and ((ad <> adTheRepublic) or
     2888          (Data.BehaviorFlags and bGender = bFemale) or
     2889          (RO.EnemyReport[Nation].Tech[adTheology] >= tsSeen)) then
     2890          Result := ad;
    26302891end;
    26312892
    26322893procedure TAI.FindBestTrade(Nation: integer; var adWanted, adGiveAway: integer);
    26332894var
    2634 i,ad,ead,adTestGiveAway: integer;
     2895  i, ad, ead, adTestGiveAway: integer;
    26352896begin
    2636 adWanted:=-1;
    2637 adGiveAway:=-1;
    2638 for ead:=0 to nAdv-5 do // no future techs
    2639   if (AdvanceValue[ead]>=$100)
    2640     and (RO.Tech[ead]<tsSeen) and (ead<>RO.ResearchTech)
    2641     and (RO.EnemyReport[Nation].Tech[ead]>=tsApplicable)
    2642     and ((adWanted<0) or (AdvanceValue[ead]>AdvanceValue[adWanted])) then
    2643     begin
    2644     adTestGiveAway:=-1;
    2645     for i:=0 to nRequestedTechs-1 do
    2646       if (Data.RequestedTechs[i]>=0)
    2647         and (Data.RequestedTechs[i] and $FFFF=Nation shl 8+ead) then
    2648         adTestGiveAway:=-2; // already requested before
    2649     if adTestGiveAway=-1 then
    2650       begin
    2651       for ad:=0 to nAdv-5 do // no future techs
    2652         if (RO.Tech[ad]>=tsApplicable)
    2653           and (ad<>RO.EnemyReport[Nation].ResearchTech)
    2654           and (RO.EnemyReport[Nation].Tech[ad]<tsSeen)
    2655           and ((Advancedness[ad]+Compromise>=Advancedness[ead]) or (ead=adScience))
    2656           and (Advancedness[ad]<=Advancedness[ead]+AdvanceValue[ead] shr 8+Compromise)
    2657           and ((adTestGiveAway<0) or (Advancedness[ad]<Advancedness[adTestGiveAway])) then
    2658           adTestGiveAway:=ad;
    2659       if adTestGiveAway>=0 then
    2660         begin
    2661         adWanted:=ead;
    2662         adGiveAway:=adTestGiveAway
    2663         end
    2664       end
     2897  adWanted := -1;
     2898  adGiveAway := -1;
     2899  for ead := 0 to nAdv - 5 do // no future techs
     2900    if (AdvanceValue[ead] >= $100) and (RO.Tech[ead] < tsSeen) and
     2901      (ead <> RO.ResearchTech) and (RO.EnemyReport[Nation].Tech[ead] >= tsApplicable) and
     2902      ((adWanted < 0) or (AdvanceValue[ead] > AdvanceValue[adWanted])) then
     2903    begin
     2904      adTestGiveAway := -1;
     2905      for i := 0 to nRequestedTechs - 1 do
     2906        if (Data.RequestedTechs[i] >= 0) and
     2907          (Data.RequestedTechs[i] and $FFFF = Nation shl 8 + ead) then
     2908          adTestGiveAway := -2; // already requested before
     2909      if adTestGiveAway = -1 then
     2910      begin
     2911        for ad := 0 to nAdv - 5 do // no future techs
     2912          if (RO.Tech[ad] >= tsApplicable) and
     2913            (ad <> RO.EnemyReport[Nation].ResearchTech) and
     2914            (RO.EnemyReport[Nation].Tech[ad] < tsSeen) and
     2915            ((Advancedness[ad] + Compromise >= Advancedness[ead]) or
     2916            (ead = adScience)) and (Advancedness[ad] <= Advancedness[ead] +
     2917            AdvanceValue[ead] shr 8 + Compromise) and
     2918            ((adTestGiveAway < 0) or (Advancedness[ad] <
     2919            Advancedness[adTestGiveAway])) then
     2920            adTestGiveAway := ad;
     2921        if adTestGiveAway >= 0 then
     2922        begin
     2923          adWanted := ead;
     2924          adGiveAway := adTestGiveAway;
     2925        end;
     2926      end;
    26652927    end;
    26662928end;
     
    26692931function TAI.WantNegotiation(Nation: integer; NegoTime: TNegoTime): boolean;
    26702932var
    2671 p1,count,adWanted,adGiveAway: integer;
     2933  p1, Count, adWanted, adGiveAway: integer;
    26722934begin
    2673 if Data.BehaviorFlags and bBarbarina=bBarbarina then
    2674   begin result:=Barbarina_WantNegotiation(Nation,NegoTime); exit end;
    2675 
    2676 if RO.Treaty[Nation]<trPeace then
    2677   begin
    2678   if Data.BehaviorFlags and bBarbarina<>0 then
    2679     begin result:=false; exit end;
    2680   count:=0;
    2681   for p1:=0 to nPl-1 do
    2682     if (p1<>me) and (1 shl p1 and RO.Alive<>0) and (RO.Treaty[p1]>=trPeace) then
    2683       inc(count);
    2684   if count>=3 then // enough peace made
    2685     begin result:=false; exit; end
    2686   end;
    2687 
    2688 NegoCause:=Routine;
    2689 case NegoTime of
    2690   EnemyCalled:
    2691     result:=true;
    2692   EndOfTurn:
    2693     if (Data.RejectTurn[suContact,Nation]>=0)
    2694       and (Data.RejectTurn[suContact,Nation]+WaitAfterReject>=RO.Turn) then
    2695       result:=false
    2696     else if RO.Treaty[Nation]<trPeace then
    2697       result:=(Data.RejectTurn[suPeace,Nation]<0)
    2698         or (Data.RejectTurn[suPeace,Nation]+WaitAfterReject<RO.Turn)
    2699     else if RO.Treaty[Nation]=trPeace then
    2700       result:= (Data.BehaviorFlags and bBarbarina=0)
    2701         and ((Data.RejectTurn[suFriendly,Nation]<0)
    2702           or (Data.RejectTurn[suFriendly,Nation]+WaitAfterReject<RO.Turn))
    2703     else
    2704       begin
    2705       FindBestTrade(Nation,adWanted,adGiveAway);
    2706       result:= adWanted>=0;
    2707       end;
    2708   BeginOfTurn:
    2709     if (Data.RejectTurn[suContact,Nation]>=0)
    2710       and (Data.RejectTurn[suContact,Nation]+WaitAfterReject>=RO.Turn) then
    2711       result:=false
    2712     else if (Data.BehaviorFlags and bGender=bMale) and Barbarina_WantCheckNegotiation(Nation) then
    2713       begin NegoCause:=CheckBarbarina; result:=true; end
    2714     else result:=false;
     2935  if Data.BehaviorFlags and bBarbarina = bBarbarina then
     2936  begin
     2937    Result := Barbarina_WantNegotiation(Nation, NegoTime);
     2938    exit;
     2939  end;
     2940
     2941  if RO.Treaty[Nation] < trPeace then
     2942  begin
     2943    if Data.BehaviorFlags and bBarbarina <> 0 then
     2944    begin
     2945      Result := False;
     2946      exit;
     2947    end;
     2948    Count := 0;
     2949    for p1 := 0 to nPl - 1 do
     2950      if (p1 <> me) and (1 shl p1 and RO.Alive <> 0) and (RO.Treaty[p1] >= trPeace) then
     2951        Inc(Count);
     2952    if Count >= 3 then // enough peace made
     2953    begin
     2954      Result := False;
     2955      exit;
     2956    end;
     2957  end;
     2958
     2959  NegoCause := Routine;
     2960  case NegoTime of
     2961    EnemyCalled:
     2962      Result := True;
     2963    EndOfTurn:
     2964      if (Data.RejectTurn[suContact, Nation] >= 0) and
     2965        (Data.RejectTurn[suContact, Nation] + WaitAfterReject >= RO.Turn) then
     2966        Result := False
     2967      else if RO.Treaty[Nation] < trPeace then
     2968        Result := (Data.RejectTurn[suPeace, Nation] < 0) or
     2969          (Data.RejectTurn[suPeace, Nation] + WaitAfterReject < RO.Turn)
     2970      else if RO.Treaty[Nation] = trPeace then
     2971        Result := (Data.BehaviorFlags and bBarbarina = 0) and
     2972          ((Data.RejectTurn[suFriendly, Nation] < 0) or
     2973          (Data.RejectTurn[suFriendly, Nation] + WaitAfterReject < RO.Turn))
     2974      else
     2975      begin
     2976        FindBestTrade(Nation, adWanted, adGiveAway);
     2977        Result := adWanted >= 0;
     2978      end;
     2979    BeginOfTurn:
     2980      if (Data.RejectTurn[suContact, Nation] >= 0) and
     2981        (Data.RejectTurn[suContact, Nation] + WaitAfterReject >= RO.Turn) then
     2982        Result := False
     2983      else if (Data.BehaviorFlags and bGender = bMale) and
     2984        Barbarina_WantCheckNegotiation(Nation) then
     2985      begin
     2986        NegoCause := CheckBarbarina;
     2987        Result := True;
     2988      end
     2989      else
     2990        Result := False;
    27152991  end;
    27162992end;
     
    27182994procedure TAI.DoNegotiation;
    27192995var
    2720 i, adWanted, adGiveAway, adToGet, Slot: integer;
    2721 BuildFreeOffer: boolean;
     2996  i, adWanted, adGiveAway, adToGet, Slot: integer;
     2997  BuildFreeOffer: boolean;
    27222998begin
    2723 if MyLastAction=scDipOffer then
    2724   if OppoAction=scDipAccept then
     2999  if MyLastAction = scDipOffer then
     3000    if OppoAction = scDipAccept then
    27253001    begin // evaluate accepted offers
    2726     AdvanceValuesSet:=false;
    2727     if (MyLastOffer.nDeliver=1) and (MyLastOffer.nCost>0)
    2728       and (MyLastOffer.Price[1]=opTech+adTheology) then
    2729       Data.TheologyPartner:=Opponent;
     3002      AdvanceValuesSet := False;
     3003      if (MyLastOffer.nDeliver = 1) and (MyLastOffer.nCost > 0) and
     3004        (MyLastOffer.Price[1] = opTech + adTheology) then
     3005        Data.TheologyPartner := Opponent;
    27303006    end
    2731   else
     3007    else
    27323008    begin // evaluate rejected offers
    2733     if MyLastOffer.nDeliver+MyLastOffer.nCost=1 then
    2734       if MyLastOffer.Price[0]=opTreaty+trPeace then
    2735         Data.RejectTurn[suPeace,Opponent]:=RO.Turn
    2736       else if MyLastOffer.Price[0]=opTreaty+trFriendlyContact then
    2737         Data.RejectTurn[suFriendly,Opponent]:=RO.Turn;
    2738     end;
    2739 if OppoAction=scDipBreak then
    2740   Data.RejectTurn[suContact,Opponent]:=RO.Turn
    2741 else if OppoAction=scDipCancelTreaty then
    2742   begin
    2743   case RO.Treaty[Opponent] of
    2744     trNone: Data.RejectTurn[suPeace,Opponent]:=RO.Turn;
    2745     trPeace: Data.RejectTurn[suFriendly,Opponent]:=RO.Turn;
    2746     end;
    2747   end;
    2748 
    2749 if Data.BehaviorFlags and bBarbarina=bBarbarina then
    2750   begin Barbarina_DoNegotiation; exit end;
    2751 
    2752 if NegoCause=CheckBarbarina then
    2753   begin Barbarina_DoCheckNegotiation; exit end;
    2754 
    2755 SetAdvanceValues; // in case no turn played after loading this game
    2756 
    2757 BuildFreeOffer:=false;
    2758 if (OppoAction=scDipStart) or (OppoAction=scDipAccept) then
    2759   BuildFreeOffer:=true
    2760 else if (OppoAction=scDipOffer) and (OppoOffer.nDeliver+OppoOffer.nCost=0) then
    2761   BuildFreeOffer:=true
    2762 else if OppoAction=scDipOffer then
    2763   begin
    2764   if (Data.BehaviorFlags and bBarbarina=0)
    2765     and (OppoOffer.nDeliver+OppoOffer.nCost=1)
    2766     and (OppoOffer.Price[0] and opMask=opTreaty)
    2767     and (integer(OppoOffer.Price[0]-opTreaty)>RO.Treaty[Opponent])
    2768     and ((OppoOffer.Price[0]-opTreaty<trAlliance) or (RO.Tech[adScience]>=tsSeen)) then
    2769     MyAction:=scDipAccept // accept all treaties
    2770   else if (RO.Treaty[Opponent]>=trPeace)
    2771     and (OppoOffer.nDeliver=1)
    2772     and (OppoOffer.Price[0] and $FFFF0000=opCivilReport+cardinal(Opponent) shl 16)
    2773     and (OppoOffer.nCost=1)
    2774     and (OppoOffer.Price[1] and $FFFF0000=opCivilReport+cardinal(me) shl 16) then
    2775     MyAction:=scDipAccept // accept exchange of civil reports
    2776   else if (OppoOffer.nDeliver=1) and (OppoOffer.nCost=1)
    2777     and (OppoOffer.Price[1] and opMask=opTech) then
     3009      if MyLastOffer.nDeliver + MyLastOffer.nCost = 1 then
     3010        if MyLastOffer.Price[0] = opTreaty + trPeace then
     3011          Data.RejectTurn[suPeace, Opponent] := RO.Turn
     3012        else if MyLastOffer.Price[0] = opTreaty + trFriendlyContact then
     3013          Data.RejectTurn[suFriendly, Opponent] := RO.Turn;
     3014    end;
     3015  if OppoAction = scDipBreak then
     3016    Data.RejectTurn[suContact, Opponent] := RO.Turn
     3017  else if OppoAction = scDipCancelTreaty then
     3018  begin
     3019    case RO.Treaty[Opponent] of
     3020      trNone: Data.RejectTurn[suPeace, Opponent] := RO.Turn;
     3021      trPeace: Data.RejectTurn[suFriendly, Opponent] := RO.Turn;
     3022    end;
     3023  end;
     3024
     3025  if Data.BehaviorFlags and bBarbarina = bBarbarina then
     3026  begin
     3027    Barbarina_DoNegotiation;
     3028    exit;
     3029  end;
     3030
     3031  if NegoCause = CheckBarbarina then
     3032  begin
     3033    Barbarina_DoCheckNegotiation;
     3034    exit;
     3035  end;
     3036
     3037  SetAdvanceValues; // in case no turn played after loading this game
     3038
     3039  BuildFreeOffer := False;
     3040  if (OppoAction = scDipStart) or (OppoAction = scDipAccept) then
     3041    BuildFreeOffer := True
     3042  else if (OppoAction = scDipOffer) and (OppoOffer.nDeliver + OppoOffer.nCost = 0) then
     3043    BuildFreeOffer := True
     3044  else if OppoAction = scDipOffer then
     3045  begin
     3046    if (Data.BehaviorFlags and bBarbarina = 0) and
     3047      (OppoOffer.nDeliver + OppoOffer.nCost = 1) and
     3048      (OppoOffer.Price[0] and opMask = opTreaty) and
     3049      (integer(OppoOffer.Price[0] - opTreaty) > RO.Treaty[Opponent]) and
     3050      ((OppoOffer.Price[0] - opTreaty < trAlliance) or
     3051      (RO.Tech[adScience] >= tsSeen)) then
     3052      MyAction := scDipAccept // accept all treaties
     3053    else if (RO.Treaty[Opponent] >= trPeace) and (OppoOffer.nDeliver = 1) and
     3054      (OppoOffer.Price[0] and $FFFF0000 = opCivilReport + cardinal(Opponent) shl 16) and
     3055      (OppoOffer.nCost = 1) and (OppoOffer.Price[1] and $FFFF0000 =
     3056      opCivilReport + cardinal(me) shl 16) then
     3057      MyAction := scDipAccept // accept exchange of civil reports
     3058    else if (OppoOffer.nDeliver = 1) and (OppoOffer.nCost = 1) and
     3059      (OppoOffer.Price[1] and opMask = opTech) then
    27783060    begin // opponent wants tech
    2779     BuildFreeOffer:=true;
    2780     adGiveAway:=OppoOffer.Price[1]-opTech;
    2781     if (OppoOffer.Price[0] and opMask=opTech)
    2782       and (MyLastAction=scDipOffer)
    2783       and (MyLastOffer.nDeliver=1) and (MyLastOffer.nCost=1)
    2784       and (OppoOffer.Price[0]=MyLastOffer.Price[1]) then
     3061      BuildFreeOffer := True;
     3062      adGiveAway := OppoOffer.Price[1] - opTech;
     3063      if (OppoOffer.Price[0] and opMask = opTech) and
     3064        (MyLastAction = scDipOffer) and (MyLastOffer.nDeliver = 1) and
     3065        (MyLastOffer.nCost = 1) and (OppoOffer.Price[0] = MyLastOffer.Price[1]) then
    27853066      begin // opponent makes counter offer, check whether to accept
    2786       adToGet:=OppoOffer.Price[0]-opTech;
    2787       if (adGiveAway=adTheRepublic) and (Data.BehaviorFlags and bGender=bFemale)
    2788         and (RO.Tech[adTheology]<tsSeen) then
    2789         begin
    2790         if adToGet=adTheology then MyAction:=scDipAccept;
     3067        adToGet := OppoOffer.Price[0] - opTech;
     3068        if (adGiveAway = adTheRepublic) and (Data.BehaviorFlags and
     3069          bGender = bFemale) and (RO.Tech[adTheology] < tsSeen) then
     3070        begin
     3071          if adToGet = adTheology then
     3072            MyAction := scDipAccept;
    27913073        end
    2792       else if (RO.Tech[adGiveAway]>=tsApplicable) and (RO.Tech[adToGet]<tsSeen)
    2793         and (AdvanceValue[adToGet]>0)
    2794         and ((Advancedness[adGiveAway]<=Advancedness[adToGet]
    2795           +AdvanceValue[adToGet] shr 8+Compromise)
    2796           or (adGiveAway=adScience) and (Opponent=Data.TheologyPartner)) then
    2797         MyAction:=scDipAccept
     3074        else if (RO.Tech[adGiveAway] >= tsApplicable) and
     3075          (RO.Tech[adToGet] < tsSeen) and (AdvanceValue[adToGet] > 0) and
     3076          ((Advancedness[adGiveAway] <= Advancedness[adToGet] +
     3077          AdvanceValue[adToGet] shr 8 + Compromise) or (adGiveAway = adScience) and
     3078          (Opponent = Data.TheologyPartner)) then
     3079          MyAction := scDipAccept;
    27983080      end
    2799     else if (OppoOffer.Price[0] and opMask=opChoose)
    2800       or (OppoOffer.Price[0] and opMask=opTech) then
     3081      else if (OppoOffer.Price[0] and opMask = opChoose) or
     3082        (OppoOffer.Price[0] and opMask = opTech) then
    28013083      begin // choose price
    2802       adWanted:=MostWanted(Opponent,OppoOffer.Price[1]-opTech);
    2803       if (OppoOffer.Price[0] and opMask=opTech)
    2804         and (Cardinal(adWanted)=OppoOffer.Price[0]-opTech) then
    2805         MyAction:=scDipAccept // opponent's offer is already perfect
    2806       else if adWanted>=0 then
     3084        adWanted := MostWanted(Opponent, OppoOffer.Price[1] - opTech);
     3085        if (OppoOffer.Price[0] and opMask = opTech) and
     3086          (cardinal(adWanted) = OppoOffer.Price[0] - opTech) then
     3087          MyAction := scDipAccept // opponent's offer is already perfect
     3088        else if adWanted >= 0 then
    28073089        begin // make improved counter offer
    2808         MyOffer.nDeliver:=1;
    2809         MyOffer.nCost:=1;
    2810         MyOffer.Price[0]:=OppoOffer.Price[1];
    2811         MyOffer.Price[1]:=opTech+adWanted;
    2812         MyAction:=scDipOffer;
    2813         BuildFreeOffer:=false
    2814         end
    2815       end;
    2816     if MyAction=scDipAccept then BuildFreeOffer:=false
     3090          MyOffer.nDeliver := 1;
     3091          MyOffer.nCost := 1;
     3092          MyOffer.Price[0] := OppoOffer.Price[1];
     3093          MyOffer.Price[1] := opTech + adWanted;
     3094          MyAction := scDipOffer;
     3095          BuildFreeOffer := False;
     3096        end;
     3097      end;
     3098      if MyAction = scDipAccept then
     3099        BuildFreeOffer := False;
    28173100    end
    2818   else BuildFreeOffer:=true
    2819   end;
    2820 if (MyAction=scDipAccept) and (OppoAction=scDipOffer) then
    2821   begin
    2822   AdvanceValuesSet:=false;
    2823   if (OppoOffer.nDeliver>0) and (OppoOffer.Price[0]=opTech+adTheology) then
    2824     Data.TheologyPartner:=Opponent
    2825   end;
    2826 
    2827 if BuildFreeOffer then
    2828   begin
    2829   if (Data.BehaviorFlags and bBarbarina=0)
    2830     and (RO.Treaty[Opponent]<trPeace)
    2831     and ((Data.RejectTurn[suPeace,Opponent]<0)
    2832       or (Data.RejectTurn[suPeace,Opponent]+WaitAfterReject<RO.Turn)) then
    2833     begin
    2834     MyOffer.nDeliver:=1;
    2835     MyOffer.nCost:=0;
    2836     MyOffer.Price[0]:=opTreaty+trPeace;
    2837     MyAction:=scDipOffer
     3101    else
     3102      BuildFreeOffer := True;
     3103  end;
     3104  if (MyAction = scDipAccept) and (OppoAction = scDipOffer) then
     3105  begin
     3106    AdvanceValuesSet := False;
     3107    if (OppoOffer.nDeliver > 0) and (OppoOffer.Price[0] = opTech + adTheology) then
     3108      Data.TheologyPartner := Opponent;
     3109  end;
     3110
     3111  if BuildFreeOffer then
     3112  begin
     3113    if (Data.BehaviorFlags and bBarbarina = 0) and (RO.Treaty[Opponent] < trPeace) and
     3114      ((Data.RejectTurn[suPeace, Opponent] < 0) or
     3115      (Data.RejectTurn[suPeace, Opponent] + WaitAfterReject < RO.Turn)) then
     3116    begin
     3117      MyOffer.nDeliver := 1;
     3118      MyOffer.nCost := 0;
     3119      MyOffer.Price[0] := opTreaty + trPeace;
     3120      MyAction := scDipOffer;
    28383121    end
    2839   else if (Data.BehaviorFlags and bBarbarina=0)
    2840     and (RO.Treaty[Opponent]=trPeace)
    2841     and ((Data.RejectTurn[suFriendly,Opponent]<0)
    2842       or (Data.RejectTurn[suFriendly,Opponent]+WaitAfterReject<RO.Turn)) then
    2843     begin
    2844     MyOffer.nDeliver:=1;
    2845     MyOffer.nCost:=0;
    2846     MyOffer.Price[0]:=opTreaty+trFriendlyContact;
    2847     MyAction:=scDipOffer
     3122    else if (Data.BehaviorFlags and bBarbarina = 0) and
     3123      (RO.Treaty[Opponent] = trPeace) and
     3124      ((Data.RejectTurn[suFriendly, Opponent] < 0) or
     3125      (Data.RejectTurn[suFriendly, Opponent] + WaitAfterReject < RO.Turn)) then
     3126    begin
     3127      MyOffer.nDeliver := 1;
     3128      MyOffer.nCost := 0;
     3129      MyOffer.Price[0] := opTreaty + trFriendlyContact;
     3130      MyAction := scDipOffer;
    28483131    end
    2849   else
    2850     begin
    2851     FindBestTrade(Opponent, adWanted, adGiveAway);
    2852     if adWanted>=0 then
    2853       begin
    2854       MyOffer.nDeliver:=1;
    2855       MyOffer.nCost:=1;
    2856       MyOffer.Price[0]:=opTech+adGiveAway;
    2857       MyOffer.Price[1]:=opTech+adWanted;
    2858       MyAction:=scDipOffer;
    2859       for i:=0 to nRequestedTechs-1 do
    2860         if Data.RequestedTechs[i]<0 then
    2861           begin Slot:=i; break end
    2862         else if (i=0) or (Data.RequestedTechs[i] shr 16
    2863           <Data.RequestedTechs[Slot] shr 16) then // find most outdated entry
    2864           Slot:=i;
    2865       Data.RequestedTechs[Slot]:=RO.Turn shl 16+Opponent shl 8+adWanted
    2866       end
    2867     end
     3132    else
     3133    begin
     3134      FindBestTrade(Opponent, adWanted, adGiveAway);
     3135      if adWanted >= 0 then
     3136      begin
     3137        MyOffer.nDeliver := 1;
     3138        MyOffer.nCost := 1;
     3139        MyOffer.Price[0] := opTech + adGiveAway;
     3140        MyOffer.Price[1] := opTech + adWanted;
     3141        MyAction := scDipOffer;
     3142        for i := 0 to nRequestedTechs - 1 do
     3143          if Data.RequestedTechs[i] < 0 then
     3144          begin
     3145            Slot := i;
     3146            break;
     3147          end
     3148          else if (i = 0) or (Data.RequestedTechs[i] shr 16 <
     3149            Data.RequestedTechs[Slot] shr 16) then // find most outdated entry
     3150            Slot := i;
     3151        Data.RequestedTechs[Slot] := RO.Turn shl 16 + Opponent shl 8 + adWanted;
     3152      end;
     3153    end;
    28683154  end;
    28693155end; // Negotiation
     
    28713157
    28723158procedure SetLeaveOutValue;
     3159
    28733160  procedure Process(ad: integer);
    28743161  var
    2875   i: integer;
    2876   begin
    2877   if LeaveOutValue[ad]<0 then
    2878     begin
    2879     LeaveOutValue[ad]:=0;
    2880     for i:=0 to 1 do if AdvPreq[ad,i]>=0 then
    2881       begin
    2882       Process(AdvPreq[ad,i]);
    2883       if AdvPreq[ad,i] in LeaveOutTechs then
    2884         inc(LeaveOutValue[ad], LeaveOutValue[AdvPreq[ad,i]]+1)
    2885       end
    2886     end
    2887   end;
     3162    i: integer;
     3163  begin
     3164    if LeaveOutValue[ad] < 0 then
     3165    begin
     3166      LeaveOutValue[ad] := 0;
     3167      for i := 0 to 1 do
     3168        if AdvPreq[ad, i] >= 0 then
     3169        begin
     3170          Process(AdvPreq[ad, i]);
     3171          if AdvPreq[ad, i] in LeaveOutTechs then
     3172            Inc(LeaveOutValue[ad], LeaveOutValue[AdvPreq[ad, i]] + 1);
     3173        end;
     3174    end;
     3175  end;
     3176
    28883177var
    2889 ad: integer;
     3178  ad: integer;
    28903179begin
    2891 FillChar(LeaveOutValue,SizeOf(LeaveOutValue),$FF);
    2892 for ad:=0 to nAdv-5 do Process(ad);
     3180  FillChar(LeaveOutValue, SizeOf(LeaveOutValue), $FF);
     3181  for ad := 0 to nAdv - 5 do
     3182    Process(ad);
    28933183end;
    28943184
    28953185
    28963186initialization
    2897 RWDataSize:=sizeof(TPersistentData);
    2898 SetLeaveOutValue;
     3187  RWDataSize := sizeof(TPersistentData);
     3188  SetLeaveOutValue;
    28993189
    29003190end.
    2901 
Note: See TracChangeset for help on using the changeset viewer.