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