Changeset 289 for trunk/AI/StdAI/AI.pas
- Timestamp:
- Feb 26, 2021, 11:55:05 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/AI/StdAI/AI.pas
r160 r289 6 6 7 7 uses 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; 12 11 13 12 const 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); 78 89 79 90 type 80 Suggestion=(suContact, suPeace, suFriendly);81 82 TPersistentData=record83 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; 86 97 // ad + p shl 8 + Turn shl 16 87 98 end; 88 99 89 TAI = class(TBarbarina)90 constructor Create(Nation: integer); override;91 92 procedure SetDataDefaults; override;93 94 protected95 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, 97 108 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; 108 119 // 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; 137 148 {$IFDEF DEBUG}procedure TraceAdvanceValues(Nation: integer);{$ENDIF} 138 149 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; 151 161 152 162 end; … … 156 166 157 167 uses 158 Pile;168 Pile; 159 169 160 170 const 161 // fine adjustment162 Aggressive=40; // 0 = never attacks, 100 = attacks even with heavy losses163 DestroyBonus=30; // percent of building cost171 // fine adjustment 172 Aggressive = 40; // 0 = never attacks, 100 = attacks even with heavy losses 173 DestroyBonus = 30; // percent of building cost 164 174 165 175 var 166 LeaveOutValue: array[0..nAdv-1] of integer;176 LeaveOutValue: array[0..nAdv - 1] of integer; 167 177 168 178 169 179 constructor TAI.Create(Nation: integer); 170 180 begin 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; 175 188 end; 176 189 177 190 procedure TAI.SetDataDefaults; 178 191 begin 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; 188 204 end; 189 205 190 206 function TAI.OnNegoRejected_CancelTreaty: boolean; 191 207 begin 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; 194 210 end; 195 211 … … 201 217 procedure TAI.RateModel(const mi: TModelInfo; var Category, Quality: integer); 202 218 var 203 EffectiveTransport: integer;219 EffectiveTransport: integer; 204 220 begin 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 213 243 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; 221 268 end 222 else223 begin224 Category:=mctGroundDefender;225 Quality:=trunc(100*(ln(mi.Defense)-ln(mi.Cost)*0.6));226 if mi.Cap and (1 shl (mcFanatic-mcFirstNonCap))<>0 then227 inc(Quality,trunc(100*ln(1.5)));228 end;229 dSea:230 if mi.Attack=0 then231 begin232 Category:=mctTransport;233 if mi.TTrans=0 then Quality:=0234 269 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); 269 294 end; 270 295 271 296 procedure TAI.RateMyModel(mix: integer; var Category, Quality: integer); 272 297 var 273 mi: TModelInfo;298 mi: TModelInfo; 274 299 begin 275 MakeModelInfo(me,mix,MyModel[mix],mi);276 RateModel(mi,Category,Quality);300 MakeModelInfo(me, mix, MyModel[mix], mi); 301 RateModel(mi, Category, Quality); 277 302 end; 278 303 279 304 function TAI.IsBetterModel(const mi: TModelInfo): boolean; 280 305 var 281 mix,Cat,Quality,Cat1,Quality1: integer;306 mix, Cat, Quality, Cat1, Quality1: integer; 282 307 begin 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; 291 320 end; 292 321 293 322 function TAI.ChooseResearchAdvance: integer; 294 323 var 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; 300 329 301 330 function MarkEntry(ad: integer): boolean; 302 331 begin 303 if RO.Tech[ad]>=tsApplicable then304 result:=false // nothing more to research here305 else if RO.Tech[ad]=tsSeen then306 begin 307 Entry[ad]:=true;308 result:=true332 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; 309 338 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; 317 348 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; 324 363 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; 334 375 end; 335 376 336 377 procedure OptimizeDevModel(OptimizeCaps: integer); 337 378 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 repeat344 Best:=-1;345 for f:=0 to nFeature-1 do346 if (1 shl f and OptimizeCaps<>0)347 and ((Feature[f].Preq<0) or IsResearched(Feature[f].Preq)) // check prerequisite348 and (RO.DevModel.Weight+Feature[f].Weight<=RO.DevModel.MaxWeight)349 and not((f>=mcFirstNonCap) and (RO.DevModel.Cap[f]>0)) then350 begin 351 if SetNewModelFeature(f,RO.DevModel.Cap[f]+1)>=rExecuted then379 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 352 393 begin 353 MakeModelInfo(me,0,RO.DevModel,mi);354 RateModel(mi,Cat,Quality);355 assert(Cat=OriginalCat);356 if Quality>BestQuality then394 MakeModelInfo(me, 0, RO.DevModel, mi); 395 RateModel(mi, Cat, Quality); 396 assert(Cat = OriginalCat); 397 if Quality > BestQuality then 357 398 begin 358 Best:=f;359 BestQuality:=Quality;399 Best := f; 400 BestQuality := Quality; 360 401 end; 361 SetNewModelFeature(f,RO.DevModel.Cap[f]-1)362 end 363 end; 364 if Best>=0 then365 SetNewModelFeature(Best,RO.DevModel.Cap[Best]+1)366 until Best<0402 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; 367 408 end; 368 409 369 410 function LeaveOutsMissing(ad: integer): boolean; 370 411 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); 380 422 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]); 386 429 end; 387 430 388 431 begin 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 411 457 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; 443 497 end; 444 498 … … 475 529 end; 476 530 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; 510 569 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 529 590 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; 535 600 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 550 620 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); 572 643 end; 573 644 574 645 function TAI.ChooseStealAdvance: integer; 575 646 var 576 ad: integer;647 ad: integer; 577 648 begin 578 result:=-1;579 for ad:=0 to nAdv-1 do580 if AdvanceStealable(ad)581 and ((result<0) or (Advancedness[ad]>Advancedness[result])) then582 result:=ad649 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; 583 654 end; 584 655 … … 589 660 590 661 const 591 twpAllowFarmland=$0001; 592 593 procedure TAI.TileWorkPlan(Loc, cix: integer; 594 var Value, NextJob, TotalWork: integer); 662 twpAllowFarmland = $0001; 663 664 procedure TAI.TileWorkPlan(Loc, cix: integer; var Value, NextJob, TotalWork: integer); 595 665 var 596 OldTile,TerrType: Cardinal;597 TileInfo: TTileInfo;666 OldTile, TerrType: cardinal; 667 TileInfo: TTileInfo; 598 668 begin 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 609 682 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 615 689 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] or621 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); 622 696 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 627 700 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] or633 Cardinal(SpecialTile(Loc,TerrType,G.lx) shl 5);634 end; 635 if (Terrain[TerrType].MineEff>0) and (RO.Government<>gDespotism) then636 begin 637 if Map[Loc] and fTerImp<>tiMine then701 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 638 711 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; 642 730 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 657 732 begin // add irrigation 658 if (RO.Government<>gDespotism)659 or (Map[Loc] and (fTerrain or fSpecial)<>fGrass) then660 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 end665 end666 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)) then733 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 670 745 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) then746 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 681 756 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; 695 772 end; 696 773 … … 698 775 procedure TAI.ProcessSettlers; 699 776 var 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); 710 787 // set Score=1 for low-priority jobs 711 788 begin 712 JobAssignment_AddJob(Loc,Job,Score);713 if (Score>1) and (District[Loc]>=0) and (District[Loc]<maxCOD) then714 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]]); 715 792 end; 716 793 717 794 procedure ReserveCityRadius(Loc: integer); 718 795 var 719 V21,RadiusLoc: integer;720 Radius: TVicinity21Loc;721 begin 722 V21_to_Loc(Loc,Radius);723 for V21:=1 to 26 do724 begin 725 RadiusLoc:=Radius[V21];726 if (RadiusLoc>=0) then727 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; 732 809 end; 733 810 734 811 procedure ScoreRoadConnections; 735 812 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 760 842 begin 761 inc(History);762 if V8>=2 then843 Inc(History); 844 if V8 >= 2 then 763 845 begin 764 inc(nFragments);765 case V8 and 1 of766 0:767 if History and 6<>0 then768 dec(nFragments);769 1:770 if History and 2<>0 then771 dec(nFragments)772 else if History and 4<>0 then846 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 773 855 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); 779 860 end 780 end 861 end; 781 862 end; 782 863 end; 783 864 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); 792 876 end; 793 877 end; … … 795 879 796 880 begin 797 fillchar(SettlerSurplus, sizeof(SettlerSurplus), 0);798 JobAssignment_Initialize;799 800 if (Data.BehaviorFlags and bBarbarina=0) or (RO.nCity<3) then801 begin 802 fillchar(TileFood,sizeof(TileFood),0);803 fillchar(ResourceScore,sizeof(ResourceScore),0);804 for Loc:=0 to MapSize-1 do805 if Map[Loc] and fTerrain<>fUNKNOWN then806 if Map[Loc] and fDeadLands<>0 then807 begin 808 if not IsResearched(adMassProduction) or (Map[Loc] and fModern<>0) then809 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; 810 894 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 817 945 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; 867 956 // some unexactness, random but always the same for this tile 868 if TestScore>BestNearCityScore then957 if TestScore > BestNearCityScore then 869 958 begin // better than all other sites in radius 870 if BestNearCityScore>0 then // found no other cities in radius959 if BestNearCityScore > 0 then // found no other cities in radius 871 960 begin 872 for V21:=1 to 26 do961 for V21 := 1 to 26 do 873 962 begin 874 RadiusLoc:=Radius[V21];875 if (RadiusLoc>=0) then876 CityScore[RadiusLoc]:=0;963 RadiusLoc := Radius[V21]; 964 if (RadiusLoc >= 0) then 965 CityScore[RadiusLoc] := 0; 877 966 end; 878 967 end; 879 CityScore[Loc]:=TestScore968 CityScore[Loc] := TestScore; 880 969 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 919 1059 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); 922 1072 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; 1034 1144 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; 1045 1147 end; // ProcessSettlers 1046 1148 … … 1052 1154 procedure TAI.DoTurn; 1053 1155 var 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} 1057 1161 begin 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} 1121 1238 1122 1239 // better government form available? 1123 if (Data.BehaviorFlags and bBarbarina=0) and (RO.Turn>=LeaveDespotism) 1124 and (RO.Government<>gAnarchy) then1125 if IsResearched(adDemocracy) then1126 begin 1127 if RO.Government<>gDemocracy then1128 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; //!!! 1129 1246 end 1130 else if IsResearched(adTheRepublic) then1131 begin 1132 if RO.Government<>gRepublic then1133 Revolution1247 else if IsResearched(adTheRepublic) then 1248 begin 1249 if RO.Government <> gRepublic then 1250 Revolution; 1134 1251 end 1135 else if IsResearched(adMonarchy) then1136 begin 1137 if RO.Government<>gMonarchy then1138 Revolution1139 end; 1140 1141 CollectModelCatStat;1142 1143 if Data.BehaviorFlags and bBarbarina=bBarbarina then1144 begin 1145 MakeColonyShipPlan;1146 Barbarina_DoTurn1252 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; 1147 1264 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 1202 1333 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; 1218 1351 1219 1352 … … 1225 1358 {$ENDIF} 1226 1359 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} 1228 1367 end; 1229 1368 … … 1231 1370 procedure TAI.TraceAdvanceValues(Nation: integer); 1232 1371 var 1233 ad: integer;1372 ad: integer; 1234 1373 begin 1235 for ad:=0 to nAdv-1 do1236 if (RO.Tech[ad]<tsSeen) and (RO.EnemyReport[Nation].Tech[ad]>=tsApplicable)1237 and (AdvanceValue[ad]>0) then1238 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; 1242 1381 end; 1382 1243 1383 {$ENDIF} 1244 1384 … … 1246 1386 procedure TAI.CheckGender; 1247 1387 var 1248 p1,NewGender: integer;1388 p1, NewGender: integer; 1249 1389 begin 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; 1259 1402 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; 1271 1417 end; 1272 1418 … … 1276 1422 procedure RateResearchAdv(ad, Time: integer); 1277 1423 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; 1284 1432 end; 1285 1433 1286 1434 procedure SetPreqValues(ad, Value: integer); 1287 1435 begin 1288 if (RO.Tech[ad]<tsSeen) and (ad<>RO.ResearchTech) then1289 begin 1290 if AdvanceValue[ad]<Value then1291 AdvanceValue[ad]:=Value;1292 if ad=adScience then1293 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); 1296 1444 end 1297 else if ad=adMassProduction then1445 else if ad = adMassProduction then 1298 1446 // preqs should be researched now 1299 else1300 begin 1301 if AdvPreq[ad,0]>=0 then1302 SetPreqValues(AdvPreq[ad,0],Value-1);1303 if AdvPreq[ad,1]>=0 then1304 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; 1307 1455 end; 1308 1456 1309 1457 procedure RateImpPreq(iix, Value: integer); 1310 1458 begin 1311 if (Value>0) and (Imp[iix].Preq>=0) then1312 inc(AdvanceValue[Imp[iix].Preq],Value);1459 if (Value > 0) and (Imp[iix].Preq >= 0) then 1460 Inc(AdvanceValue[Imp[iix].Preq], Value); 1313 1461 end; 1314 1462 1315 1463 var 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; 1319 1467 begin 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 1338 1490 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 1345 1510 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 1348 1516 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); 1353 1519 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); 1482 1646 end; 1483 1647 1484 1648 procedure TAI.AnalyzeMap; 1485 1649 var 1486 cix,Loc,Loc1,V8,f1,p1: integer;1487 Adjacent: TVicinity8Loc;1650 cix, Loc, Loc1, V8, f1, p1: integer; 1651 Adjacent: TVicinity8Loc; 1488 1652 begin 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: 1507 1672 begin // adjacent formations are not completely discovered 1508 V8_to_Loc(Loc,Adjacent);1509 for V8:=0 to 7 do1510 begin 1511 Loc1:=Adjacent[V8];1512 if Loc1>=0 then1673 V8_to_Loc(Loc, Adjacent); 1674 for V8 := 0 to 7 do 1675 begin 1676 Loc1 := Adjacent[V8]; 1677 if Loc1 >= 0 then 1513 1678 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: 1523 1689 begin // nation present in adjacent formations 1524 V8_to_Loc(Loc,Adjacent);1525 for V8:=0 to 7 do1526 begin 1527 Loc1:=Adjacent[V8];1528 if Loc1>=0 then1690 V8_to_Loc(Loc, Adjacent); 1691 for V8 := 0 to 7 do 1692 begin 1693 Loc1 := Adjacent[V8]; 1694 if Loc1 >= 0 then 1529 1695 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; 1561 1731 end; 1562 1732 1563 1733 procedure TAI.CollectModelCatStat; 1564 1734 var 1565 i,uix,Cat,mix,Quality: integer;1735 i, uix, Cat, mix, Quality: integer; 1566 1736 begin 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 1582 1754 begin 1583 RateMyModel(mix,Cat,Quality);1584 ModelCat[mix]:=Cat;1585 ModelQuality[mix]:=Quality;1586 if (Cat>=0) and (Quality>ModelBestQuality[Cat]) then1587 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; 1588 1760 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; 1611 1785 end; 1612 1786 … … 1614 1788 procedure TAI.MoveUnitsHome; 1615 1789 const 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); 1618 1792 var 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; 1626 1800 1627 1801 function IsBombarded(cix: integer): boolean; 1628 1802 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; 1645 1824 end; 1646 1825 1647 1826 procedure TryUtilize(uix: integer); 1648 1827 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; 1663 1844 end; 1664 1845 1665 1846 procedure FindDestination(uix: integer); 1666 1847 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; 1707 1889 end; 1708 1890 1709 1891 begin 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 1739 1999 repeat 1740 if Loop=FirstSurplusLoop[Cat] then1741 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do1742 if (Loc>=0) and (Destination[uix]<0) and (Master<0)1743 and (ModelCat[mix]=Cat)1744 and (ModelQuality[mix]<0) then1745 TryUtilize(uix);1746 1747 2000 fillchar(LocNeed, MapSize, 0); 1748 2001 fillchar(DistrictNeed, sizeof(DistrictNeed), 0); 1749 2002 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 1757 2009 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]]); 1771 2013 end; 1772 1773 complete:= Loop>=FirstSurplusLoop[Cat]; 1774 for i:=nModelOrder-1 downto 0 do1775 begin1776 for Fortified:=true downto falsedo1777 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do1778 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) then2014 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 1782 2024 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 1788 2033 end; 1789 1790 for uix:=0 to RO.nUn-1 do with MyUnit[uix] do1791 if (mix=ModelOrder[i])1792 and (Loc>=0) and (Destination[uix]<0) and (Master<0) then1793 if (District[Loc]>=0) and (District[Loc]<maxCOD)1794 and (DistrictNeed[District[Loc]]=0) then1795 else1796 begin // unassigned unit1797 FindDestination(uix);1798 if Destination[uix]>=0 then complete:=false;1799 end;1800 end;1801 inc(Loop)1802 2034 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; 1859 2057 end; // MoveUnitsHome 1860 2058 … … 1862 2060 procedure TAI.CheckAttack(uix: integer); 1863 2061 var 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; 1871 2069 1872 2070 begin 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 1889 2088 begin // enemy unit 1890 assert(TestTime<$1000);1891 Unit_FindEnemyDefender(TestLoc,euix);1892 if RO.Treaty[RO.EnemyUn[euix].Owner]<trPeace then1893 if Unit_AttackForecast(uix,TestLoc,$800-TestTime,AttackForecast) then2089 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 1894 2093 begin // attack possible, but advantageous? 1895 if AttackForecast=0 then2094 if AttackForecast = 0 then 1896 2095 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; 1899 2098 end 1900 else if AttackForecast>0 then2099 else if AttackForecast > 0 then 1901 2100 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; 1904 2103 end 1905 else // own unit would be destroyed2104 else // own unit would be destroyed 1906 2105 begin 1907 MyDamage:=Health+DestroyBonus;1908 EnemyDamage:=RO.EnemyUn[euix].Health+AttackForecast;2106 MyDamage := Health + DestroyBonus; 2107 EnemyDamage := RO.EnemyUn[euix].Health + AttackForecast; 1909 2108 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 1915 2115 begin 1916 if TestScore>AttackScore then1917 BestCount:=0;1918 if TestScore>=AttackScore then2116 if TestScore > AttackScore then 2117 BestCount := 0; 2118 if TestScore >= AttackScore then 1919 2119 begin 1920 inc(BestCount);1921 if random(BestCount)=0 then2120 Inc(BestCount); 2121 if random(BestCount) = 0 then 1922 2122 begin 1923 AttackScore:=TestScore;1924 AttackLoc:=TestLoc;1925 end 2123 AttackScore := TestScore; 2124 AttackLoc := TestLoc; 2125 end; 1926 2126 end; 1927 end 2127 end; 1928 2128 end; 1929 2129 end // enemy unit 1930 2130 1931 else if ((Tile and fCity)<>0) and ((Tile and fOwned)=0) then2131 else if ((Tile and fCity) <> 0) and ((Tile and fOwned) = 0) then 1932 2132 // enemy city 1933 2133 1934 else2134 else 1935 2135 begin // no enemy city or unit here 1936 V8_to_Loc(TestLoc,Adjacent);1937 for V8:=0 to 7 do2136 V8_to_Loc(TestLoc, Adjacent); 2137 for V8 := 0 to 7 do 1938 2138 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; 1951 2153 end; 1952 2154 end; // no enemy city or unit here 1953 2155 end; // while Pile.Get 1954 Pile.Free;1955 1956 if AttackLoc>=0 then1957 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 then1963 if Movement<100 then1964 Exhausted:=true1965 else2156 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 1966 2168 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); 1970 2172 end; 1971 2173 end 1972 else Exhausted:=true; 1973 until Exhausted; 2174 else 2175 Exhausted := True; 2176 until Exhausted; 1974 2177 end; 1975 2178 end; // CheckAttack … … 1978 2181 procedure TAI.Patrol(uix: integer); 1979 2182 const 1980 DistanceScore=4;2183 DistanceScore = 4; 1981 2184 var 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; 1988 2191 1989 2192 begin 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 2012 2216 // enemy unit 2013 2217 2014 else if ((Tile and fCity)<>0) and ((Tile and fOwned)=0) then2015 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 unknown2019 or (RO.Treaty[RO.Territory[TestLoc]] <trPeace)) then2020 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! 2021 2225 end 2022 2226 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 2023 2280 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; 2076 2283 end; 2077 2284 end; // Patrol … … 2079 2286 procedure TAI.AttackAndPatrol; 2080 2287 const 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); 2084 2291 var 2085 iCat,uix,uix1: integer;2086 IsPatrolUnit,Fortified: boolean;2292 iCat, uix, uix1: integer; 2293 IsPatrolUnit, Fortified: boolean; 2087 2294 begin 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; 2131 2344 end; // AttackAndPatrol 2132 2345 … … 2134 2347 function TAI.HavePort: boolean; 2135 2348 var 2136 V8, cix,AdjacentLoc,f: integer;2137 Adjacent: TVicinity8Loc;2349 V8, cix, AdjacentLoc, f: integer; 2350 Adjacent: TVicinity8Loc; 2138 2351 begin 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; 2154 2370 end; 2155 2371 … … 2157 2373 procedure TAI.SetCityProduction; 2158 2374 var 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; 2168 2385 2169 2386 procedure TryBuild(Improvement: integer); 2170 2387 begin 2171 if (NewImprovement=imTrGoods) // not already improvement of higher priority found2172 and (MyCity[cix].Built[Improvement]=0) // not built yet2173 and ((Imp[Improvement].Preq=preNone)2174 or (RO.Tech[Imp[Improvement].Preq]>=tsApplicable))2175 andCity_Improvable(cix, Improvement) then2176 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; 2177 2394 end; 2178 2395 2179 2396 procedure TryDestruct(Improvement: integer); 2180 2397 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); 2185 2404 { if (CurrentImprovementProject>=0) 2186 2405 and (Imp[CurrentImprovementProject].Kind in [ikCommon,ikNatGlobal,ikNatLocal]) 2187 2406 and ((Imp[CurrentImprovementProject].Cost*3-Imp[Improvement].Cost*2) 2188 2407 *BuildCostMod[G.Difficulty[me]]>MyCity[cix].Prod*(12*3)) then} 2189 Destructed:=true2408 Destructed := True; 2190 2409 end; 2191 2410 2192 2411 function ChooseBuildModel(Cat: integer): integer; 2193 2412 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); 2202 2425 end; 2203 2426 … … 2205 2428 // find military production cities 2206 2429 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; 2255 2484 { if (cixWorst>=0) 2256 2485 and (Share-CityResult[cixWorst]*2>=Total*MilProdShare div 100) then … … 2258 2487 end; 2259 2488 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; 2280 2511 end; 2281 2512 2282 2513 procedure ChangeHomeCities; 2283 2514 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 2294 2543 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; 2297 2561 end; 2298 gMonarchy, gCommunism: 2562 end; 2563 end; 2564 2565 begin 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 2299 2608 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; 2302 2622 end; 2303 else 2623 2624 if RO.Turn = 0 then 2304 2625 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); 2307 2638 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 2319 2648 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 2369 2805 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); 2470 2808 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; 2580 2838 end; // SetCityProduction 2581 2839 … … 2583 2841 function TAI.ChooseGovernment: integer; 2584 2842 begin 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; 2595 2856 end; 2596 2857 … … 2602 2863 function TAI.MostWanted(Nation, adGiveAway: integer): integer; 2603 2864 var 2604 ad: integer;2865 ad: integer; 2605 2866 begin 2606 result:=-1;2607 if RO.Tech[adGiveAway]>=tsApplicable then2608 if (adGiveAway=adTheRepublic) and (Data.BehaviorFlags and bGender=bFemale)2609 and (RO.Tech[adTheology]<tsSeen) then2610 begin 2611 if RO.EnemyReport[Nation].Tech[adTheology]>=tsApplicable then2612 result:=adTheology2867 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; 2613 2874 end 2614 else for ad:=0 to nAdv-5 do // no future techs2615 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 opponent2622 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)) then2629 result:=ad2875 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; 2630 2891 end; 2631 2892 2632 2893 procedure TAI.FindBestTrade(Nation: integer; var adWanted, adGiveAway: integer); 2633 2894 var 2634 i,ad,ead,adTestGiveAway: integer;2895 i, ad, ead, adTestGiveAway: integer; 2635 2896 begin 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; 2665 2927 end; 2666 2928 end; … … 2669 2931 function TAI.WantNegotiation(Nation: integer; NegoTime: TNegoTime): boolean; 2670 2932 var 2671 p1,count,adWanted,adGiveAway: integer;2933 p1, Count, adWanted, adGiveAway: integer; 2672 2934 begin 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; 2715 2991 end; 2716 2992 end; … … 2718 2994 procedure TAI.DoNegotiation; 2719 2995 var 2720 i, adWanted, adGiveAway, adToGet, Slot: integer;2721 BuildFreeOffer: boolean;2996 i, adWanted, adGiveAway, adToGet, Slot: integer; 2997 BuildFreeOffer: boolean; 2722 2998 begin 2723 if MyLastAction=scDipOffer then2724 if OppoAction=scDipAccept then2999 if MyLastAction = scDipOffer then 3000 if OppoAction = scDipAccept then 2725 3001 begin // evaluate accepted offers 2726 AdvanceValuesSet:=false;2727 if (MyLastOffer.nDeliver=1) and (MyLastOffer.nCost>0)2728 and (MyLastOffer.Price[1]=opTech+adTheology) then2729 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; 2730 3006 end 2731 else3007 else 2732 3008 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 2778 3060 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 2785 3066 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; 2791 3073 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)) then2797 MyAction:=scDipAccept3074 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; 2798 3080 end 2799 else if (OppoOffer.Price[0] and opMask=opChoose)2800 or (OppoOffer.Price[0] and opMask=opTech) then3081 else if (OppoOffer.Price[0] and opMask = opChoose) or 3082 (OppoOffer.Price[0] and opMask = opTech) then 2801 3083 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) then2805 MyAction:=scDipAccept // opponent's offer is already perfect2806 else if adWanted>=0 then3084 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 2807 3089 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; 2817 3100 end 2818 else BuildFreeOffer:=true2819 end;2820 if (MyAction=scDipAccept) and (OppoAction=scDipOffer) then 2821 begin2822 AdvanceValuesSet:=false;2823 if (OppoOffer.nDeliver>0) and (OppoOffer.Price[0]=opTech+adTheology) then2824 Data.TheologyPartner:=Opponent2825 end;2826 2827 if BuildFreeOffer then 2828 begin2829 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)) then2833 begin 2834 MyOffer.nDeliver:=1;2835 MyOffer.nCost:=0;2836 MyOffer.Price[0]:=opTreaty+trPeace;2837 MyAction:=scDipOffer3101 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; 2838 3121 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)) then2843 begin 2844 MyOffer.nDeliver:=1;2845 MyOffer.nCost:=0;2846 MyOffer.Price[0]:=opTreaty+trFriendlyContact;2847 MyAction:=scDipOffer3122 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; 2848 3131 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; 2868 3154 end; 2869 3155 end; // Negotiation … … 2871 3157 2872 3158 procedure SetLeaveOutValue; 3159 2873 3160 procedure Process(ad: integer); 2874 3161 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 2888 3177 var 2889 ad: integer;3178 ad: integer; 2890 3179 begin 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); 2893 3183 end; 2894 3184 2895 3185 2896 3186 initialization 2897 RWDataSize:=sizeof(TPersistentData);2898 SetLeaveOutValue;3187 RWDataSize := sizeof(TPersistentData); 3188 SetLeaveOutValue; 2899 3189 2900 3190 end. 2901
Note:
See TracChangeset
for help on using the changeset viewer.