Changeset 160 for trunk/AI/StdAI/CustomAI.pas
- Timestamp:
- Mar 6, 2019, 8:10:23 AM (7 years ago)
- File:
-
- 1 edited
-
trunk/AI/StdAI/CustomAI.pas (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/AI/StdAI/CustomAI.pas
r124 r160 5 5 6 6 uses 7 {$IFDEF DEBUG}SysUtils, {$ENDIF} // necessary for debug exceptions7 {$IFDEF DEBUG}SysUtils,{$ENDIF} // necessary for debug exceptions 8 8 Protocol; 9 9 10 10 type 11 TNegoTime = (BeginOfTurn, EndOfTurn, EnemyCalled); 12 13 TCustomAI = class 14 public 15 procedure Process(Command: integer; var Data); 16 17 // overridables 18 constructor Create(Nation: integer); virtual; 19 destructor Destroy; override; 20 procedure SetDataDefaults; virtual; 21 procedure SetDataRandom; virtual; 22 procedure OnBeforeEnemyAttack(UnitInfo: TUnitInfo; 23 ToLoc, EndHealth, EndHealthDef: integer); virtual; 24 procedure OnBeforeEnemyCapture(UnitInfo: TUnitInfo; 25 ToLoc: integer); virtual; 26 procedure OnAfterEnemyAttack; virtual; 27 procedure OnAfterEnemyCapture; virtual; 28 29 protected 30 me: integer; // index of the controlled nation 31 RO: ^TPlayerContext; 32 Map: ^TTileList; 33 MyUnit: ^TUnList; 34 MyCity: ^TCityList; 35 MyModel: ^TModelList; 36 37 cixStateImp: array [imPalace .. imSpacePort] of integer; 38 39 // negotiation 40 Opponent: integer; 41 // nation i'm in negotiation with, -1 indicates no-negotiation mode 42 MyAction, MyLastAction, OppoAction: integer; 43 MyOffer, MyLastOffer, OppoOffer: TOffer; 44 45 // overridables 46 procedure DoTurn; virtual; 47 procedure DoNegotiation; virtual; 48 function ChooseResearchAdvance: integer; virtual; 49 function ChooseStealAdvance: integer; virtual; 50 function ChooseGovernment: integer; virtual; 51 function WantNegotiation(Nation: integer; NegoTime: TNegoTime) 52 : boolean; virtual; 53 function OnNegoRejected_CancelTreaty: boolean; virtual; 54 55 // general functions 56 function IsResearched(Advance: integer): boolean; 57 function ResearchCost: integer; 58 function ChangeAttitude(Nation, Attitude: integer): integer; 59 function Revolution: integer; 60 function ChangeRates(Tax, Lux: integer): integer; 61 function PrepareNewModel(Domain: integer): integer; 62 function SetNewModelFeature(F, Count: integer): integer; 63 function AdvanceResearchable(Advance: integer): boolean; 64 function AdvanceStealable(Advance: integer): boolean; 65 function GetJobProgress(Loc: integer; 66 var JobProgress: TJobProgressData): boolean; 67 function DebugMessage(Level: integer; Text: string): boolean; 68 function SetDebugMap(var DebugMap): boolean; 69 70 // unit functions 71 procedure Unit_FindMyDefender(Loc: integer; var uix: integer); 72 procedure Unit_FindEnemyDefender(Loc: integer; var euix: integer); 73 function Unit_Move(uix, ToLoc: integer): integer; 74 function Unit_Step(uix, ToLoc: integer): integer; 75 function Unit_Attack(uix, ToLoc: integer): integer; 76 function Unit_DoMission(uix, MissionType, ToLoc: integer): integer; 77 function Unit_MoveForecast(uix, ToLoc: integer; 78 var RemainingMovement: integer): boolean; 79 function Unit_AttackForecast(uix, ToLoc, AttackMovement: integer; 80 var RemainingHealth: integer): boolean; 81 function Unit_DefenseForecast(euix, ToLoc: integer; 82 var RemainingHealth: integer): boolean; 83 function Unit_Disband(uix: integer): integer; 84 function Unit_StartJob(uix, NewJob: integer): integer; 85 function Unit_SetHomeHere(uix: integer): integer; 86 function Unit_Load(uix: integer): integer; 87 function Unit_Unload(uix: integer): integer; 88 function Unit_SelectTransport(uix: integer): integer; 89 function Unit_AddToCity(uix: integer): integer; 90 91 // city functions 92 procedure City_FindMyCity(Loc: integer; var cix: integer); 93 procedure City_FindEnemyCity(Loc: integer; var ecix: integer); 94 function City_HasProject(cix: integer): boolean; 95 function City_CurrentImprovementProject(cix: integer): integer; 96 function City_CurrentUnitProject(cix: integer): integer; 97 function City_GetTileInfo(cix, TileLoc: integer; 98 var TileInfo: TTileInfo): integer; 99 function City_GetReport(cix: integer; var Report: TCityReport): integer; 100 function City_GetHypoReport(cix, HypoTiles, HypoTax, HypoLux: integer; 101 var Report: TCityReport): integer; 102 function City_GetReportNew(cix: integer; 103 var Report: TCityReportNew): integer; 104 function City_GetHypoReportNew(cix, HypoTiles, HypoTaxRate, 105 HypoLuxuryRate: integer; var Report: TCityReportNew): integer; 106 function City_GetAreaInfo(cix: integer; 107 var AreaInfo: TCityAreaInfo): integer; 108 function City_StartUnitProduction(cix, mix: integer): integer; 109 function City_StartEmigration(cix, mix: integer; 110 AllowDisbandCity, AsConscripts: boolean): integer; 111 function City_StartImprovement(cix, iix: integer): integer; 112 function City_Improvable(cix, iix: integer): boolean; 113 function City_StopProduction(cix: integer): integer; 114 function City_BuyProject(cix: integer): integer; 115 function City_SellImprovement(cix, iix: integer): integer; 116 function City_RebuildImprovement(cix, iix: integer): integer; 117 function City_SetTiles(cix, NewTiles: integer): integer; 118 procedure City_OptimizeTiles(cix: integer; 119 ResourceWeights: integer = rwMaxGrowth); 120 121 // negotiation 122 function Nego_CheckMyAction: integer; 123 124 private 125 HaveTurned: boolean; 126 UnwantedNego: set of 0 .. nPl - 1; 127 Contacted: set of 0 .. nPl - 1; 128 procedure StealAdvance; 11 TNegoTime=(BeginOfTurn, EndOfTurn, EnemyCalled); 12 13 TCustomAI=class 14 public 15 procedure Process(Command: integer; var Data); 16 17 // overridables 18 constructor Create(Nation: integer); virtual; 19 destructor Destroy; override; 20 procedure SetDataDefaults; virtual; 21 procedure SetDataRandom; virtual; 22 procedure OnBeforeEnemyAttack(UnitInfo: TUnitInfo; 23 ToLoc, EndHealth, EndHealthDef: integer); virtual; 24 procedure OnBeforeEnemyCapture(UnitInfo: TUnitInfo; ToLoc: integer); virtual; 25 procedure OnAfterEnemyAttack; virtual; 26 procedure OnAfterEnemyCapture; virtual; 27 28 protected 29 me: integer; // index of the controlled nation 30 RO: ^TPlayerContext; 31 Map: ^TTileList; 32 MyUnit: ^TUnList; 33 MyCity: ^TCityList; 34 MyModel: ^TModelList; 35 36 cixStateImp: array[imPalace..imSpacePort] of integer; 37 38 // negotiation 39 Opponent: integer; // nation i'm in negotiation with, -1 indicates no-negotiation mode 40 MyAction, MyLastAction, OppoAction: integer; 41 MyOffer, MyLastOffer, OppoOffer: TOffer; 42 43 // overridables 44 procedure DoTurn; virtual; 45 procedure DoNegotiation; virtual; 46 function ChooseResearchAdvance: integer; virtual; 47 function ChooseStealAdvance: integer; virtual; 48 function ChooseGovernment: integer; virtual; 49 function WantNegotiation(Nation: integer; NegoTime: TNegoTime): boolean; virtual; 50 function OnNegoRejected_CancelTreaty: boolean; virtual; 51 52 // general functions 53 function IsResearched(Advance: integer): boolean; 54 function ResearchCost: integer; 55 function ChangeAttitude(Nation, Attitude: integer): integer; 56 function Revolution: integer; 57 function ChangeRates(Tax,Lux: integer): integer; 58 function PrepareNewModel(Domain: integer): integer; 59 function SetNewModelFeature(F, Count: integer): integer; 60 function AdvanceResearchable(Advance: integer): boolean; 61 function AdvanceStealable(Advance: integer): boolean; 62 function GetJobProgress(Loc: integer; var JobProgress: TJobProgressData): boolean; 63 function DebugMessage(Level: integer; Text: string): boolean; 64 function SetDebugMap(var DebugMap): boolean; 65 66 // unit functions 67 procedure Unit_FindMyDefender(Loc: integer; var uix: integer); 68 procedure Unit_FindEnemyDefender(Loc: integer; var euix: integer); 69 function Unit_Move(uix,ToLoc: integer): integer; 70 function Unit_Step(uix,ToLoc: integer): integer; 71 function Unit_Attack(uix,ToLoc: integer): integer; 72 function Unit_DoMission(uix,MissionType,ToLoc: integer): integer; 73 function Unit_MoveForecast(uix,ToLoc: integer; var RemainingMovement: integer): boolean; 74 function Unit_AttackForecast(uix,ToLoc,AttackMovement: integer; var RemainingHealth: integer): boolean; 75 function Unit_DefenseForecast(euix,ToLoc: integer; var RemainingHealth: integer): boolean; 76 function Unit_Disband(uix: integer): integer; 77 function Unit_StartJob(uix,NewJob: integer): integer; 78 function Unit_SetHomeHere(uix: integer): integer; 79 function Unit_Load(uix: integer): integer; 80 function Unit_Unload(uix: integer): integer; 81 function Unit_SelectTransport(uix: integer): integer; 82 function Unit_AddToCity(uix: integer): integer; 83 84 // city functions 85 procedure City_FindMyCity(Loc: integer; var cix: integer); 86 procedure City_FindEnemyCity(Loc: integer; var ecix: integer); 87 function City_HasProject(cix: integer): boolean; 88 function City_CurrentImprovementProject(cix: integer): integer; 89 function City_CurrentUnitProject(cix: integer): integer; 90 function City_GetTileInfo(cix,TileLoc: integer; var TileInfo: TTileInfo): integer; 91 function City_GetReport(cix: integer; var Report: TCityReport): integer; 92 function City_GetHypoReport(cix, HypoTiles, HypoTax, HypoLux: integer; var Report: TCityReport): integer; 93 function City_GetReportNew(cix: integer; var Report: TCityReportNew): integer; 94 function City_GetHypoReportNew(cix, HypoTiles, HypoTaxRate, HypoLuxuryRate: integer; var Report: TCityReportNew): integer; 95 function City_GetAreaInfo(cix: integer; var AreaInfo: TCityAreaInfo): integer; 96 function City_StartUnitProduction(cix,mix: integer): integer; 97 function City_StartEmigration(cix,mix: integer; AllowDisbandCity, AsConscripts: boolean): integer; 98 function City_StartImprovement(cix,iix: integer): integer; 99 function City_Improvable(cix,iix: integer): boolean; 100 function City_StopProduction(cix: integer): integer; 101 function City_BuyProject(cix: integer): integer; 102 function City_SellImprovement(cix,iix: integer): integer; 103 function City_RebuildImprovement(cix,iix: integer): integer; 104 function City_SetTiles(cix,NewTiles: integer): integer; 105 procedure City_OptimizeTiles(cix: integer; ResourceWeights: cardinal = rwMaxGrowth); 106 107 // negotiation 108 function Nego_CheckMyAction: integer; 109 110 private 111 HaveTurned: boolean; 112 UnwantedNego: set of 0..nPl-1; 113 Contacted: set of 0..nPl-1; 114 procedure StealAdvance; 129 115 end; 130 116 131 var 132 Server: TServerCall; 133 G: TNewGameData; 134 RWDataSize, MapSize: integer; 135 decompose24: cardinal; 136 nodata: pointer; 117 118 var 119 Server: TServerCall; 120 G: TNewGameData; 121 RWDataSize, MapSize: integer; 122 decompose24: cardinal; 123 nodata: pointer; 137 124 138 125 const 139 CityOwnTile = 13; // = ab_to_V21(0,0) 140 141 // additional return codes 142 rLocationReached = $00010000; 143 // Unit_Move: move was not interrupted, location reached 144 rMoreTurns = $00020000; 145 // Unit_Move: move was not interrupted, location not reached yet 126 CityOwnTile = 13; // = ab_to_V21(0,0) 127 128 // additional return codes 129 rLocationReached= $00010000; // Unit_Move: move was not interrupted, location reached 130 rMoreTurns= $00020000; // Unit_Move: move was not interrupted, location not reached yet 146 131 147 132 type 148 TVicinity8Loc = array [0 .. 7] of integer; 149 TVicinity21Loc = array [0 .. 27] of integer; 133 TVicinity8Loc=array[0..7] of integer; 134 TVicinity21Loc=array[0..27] of integer; 135 150 136 151 137 procedure Init(NewGameData: TNewGameData); 152 138 153 procedure ab_to_Loc(Loc0, a,b: integer; var Loc: integer);154 procedure Loc_to_ab(Loc0, Loc: integer; var a,b: integer);155 procedure ab_to_V8(a, b: integer; var V8: integer);156 procedure V8_to_ab(V8: integer; var a, b: integer);157 procedure ab_to_V21(a, b: integer; var V21: integer);158 procedure V21_to_ab(V21: integer; var a, b: integer);139 procedure ab_to_Loc(Loc0,a,b: integer; var Loc: integer); 140 procedure Loc_to_ab(Loc0,Loc: integer; var a,b: integer); 141 procedure ab_to_V8(a,b: integer; var V8: integer); 142 procedure V8_to_ab(V8: integer; var a,b: integer); 143 procedure ab_to_V21(a,b: integer; var V21: integer); 144 procedure V21_to_ab(V21: integer; var a,b: integer); 159 145 procedure V8_to_Loc(Loc0: integer; var VicinityLoc: TVicinity8Loc); 160 146 procedure V21_to_Loc(Loc0: integer; var VicinityLoc: TVicinity21Loc); 147 function Distance(Loc0,Loc1: integer): integer; 148 161 149 162 150 implementation 163 151 164 152 const 165 ab_v8: array [-4 .. 4] of integer = (5, 6, 7, 4, -1, 0, 3, 2, 1); 166 v8_a: array [0 .. 7] of integer = (1, 1, 0, -1, -1, -1, 0, 1); 167 v8_b: array [0 .. 7] of integer = (0, 1, 1, 1, 0, -1, -1, -1); 168 169 procedure ab_to_Loc(Loc0, a, b: integer; var Loc: integer); 170 { relative location from Loc0 } 171 var 172 y0: integer; 173 begin 174 assert((Loc0 >= 0) and (Loc0 < MapSize) and (a - b + G.lx >= 0)); 175 y0 := cardinal(Loc0) * decompose24 shr 24; 176 Loc := (Loc0 + (a - b + y0 and 1 + G.lx + G.lx) shr 1) mod G.lx + G.lx * 177 (y0 + a + b); 178 if Loc >= MapSize then 179 Loc := -$1000 180 end; 181 182 procedure Loc_to_ab(Loc0, Loc: integer; var a, b: integer); 153 ab_v8: array[-4..4] of integer = (5,6,7,4,-1,0,3,2,1); 154 v8_a: array[0..7] of integer = (1,1,0,-1,-1,-1,0,1); 155 v8_b: array[0..7] of integer = (0,1,1,1,0,-1,-1,-1); 156 157 158 procedure ab_to_Loc(Loc0,a,b: integer; var Loc: integer); 159 {relative location from Loc0} 160 var 161 y0: integer; 162 begin 163 assert((Loc0>=0) and (Loc0<MapSize) and (a-b+G.lx>=0)); 164 y0:=cardinal(Loc0)*decompose24 shr 24; 165 Loc:=(Loc0+(a-b+y0 and 1+G.lx+G.lx) shr 1) mod G.lx +G.lx*(y0+a+b); 166 if Loc>=MapSize then Loc:=-$1000 167 end; 168 169 procedure Loc_to_ab(Loc0,Loc: integer; var a,b: integer); 183 170 {$IFDEF FPC} // freepascal 184 171 var 185 dx,dy: integer;186 begin 187 dx := ((Loc mod G.lx * 2 + Loc div G.lx and 1) - 188 (Loc0 mod G.lx * 2 + Loc0 div G.lx and 1) + 3 * G.lx) mod (2 * G.lx) -G.lx;189 dy := Loc div G.lx -Loc0 div G.lx;190 a := (dx +dy) div 2;191 b := (dy -dx) div 2;172 dx,dy: integer; 173 begin 174 dx:=((Loc mod G.lx *2 +Loc div G.lx and 1) 175 -(Loc0 mod G.lx *2 +Loc0 div G.lx and 1)+3*G.lx) mod (2*G.lx) -G.lx; 176 dy:=Loc div G.lx-Loc0 div G.lx; 177 a:=(dx+dy) div 2; 178 b:=(dy-dx) div 2; 192 179 end; 193 180 {$ELSE} // delphi 194 181 register; 195 182 asm 196 push ebx197 198 // calculate199 push ecx200 div byte ptr [G]201 xor ebx,ebx202 mov bl,ah // ebx:=Loc0 mod G.lx203 mov ecx,eax204 and ecx,$000000FF // ecx:=Loc0 div G.lx205 mov eax,edx206 div byte ptr [G]207 xor edx,edx208 mov dl,ah // edx:=Loc mod G.lx209 and eax,$000000FF // eax:=Loc div G.lx210 sub edx,ebx // edx:=Loc mod G.lx-Loc0 mod G.lx211 mov ebx,eax212 sub ebx,ecx // ebx:=dy213 and eax,1214 and ecx,1215 add edx,edx216 add eax,edx217 sub eax,ecx // eax:=dx, not normalized218 pop ecx219 220 // normalize221 mov edx,dword ptr [G]222 cmp eax,edx223 jl @a183 push ebx 184 185 // calculate 186 push ecx 187 div byte ptr [G] 188 xor ebx,ebx 189 mov bl,ah // ebx:=Loc0 mod G.lx 190 mov ecx,eax 191 and ecx,$000000FF // ecx:=Loc0 div G.lx 192 mov eax,edx 193 div byte ptr [G] 194 xor edx,edx 195 mov dl,ah // edx:=Loc mod G.lx 196 and eax,$000000FF // eax:=Loc div G.lx 197 sub edx,ebx // edx:=Loc mod G.lx-Loc0 mod G.lx 198 mov ebx,eax 199 sub ebx,ecx // ebx:=dy 200 and eax,1 201 and ecx,1 202 add edx,edx 203 add eax,edx 204 sub eax,ecx // eax:=dx, not normalized 205 pop ecx 206 207 // normalize 208 mov edx,dword ptr [G] 209 cmp eax,edx 210 jl @a 224 211 sub eax,edx 225 212 sub eax,edx 226 213 jmp @ok 227 214 @a: 228 neg edx229 cmp eax,edx230 jnl @ok215 neg edx 216 cmp eax,edx 217 jnl @ok 231 218 sub eax,edx 232 219 sub eax,edx 233 220 234 // return results221 // return results 235 222 @ok: 236 mov edx,ebx237 sub edx,eax238 add eax,ebx239 sar edx,1 // edx:=b240 mov ebx,[b]241 mov [ebx],edx242 sar eax,1 // eax:=a243 mov [a],eax244 245 pop ebx223 mov edx,ebx 224 sub edx,eax 225 add eax,ebx 226 sar edx,1 // edx:=b 227 mov ebx,[b] 228 mov [ebx],edx 229 sar eax,1 // eax:=a 230 mov [a],eax 231 232 pop ebx 246 233 end; 247 234 {$ENDIF} 248 235 249 procedure ab_to_V8(a, b: integer; var V8: integer); 250 begin 251 assert((abs(a) <= 1) and (abs(b) <= 1) and ((a <> 0) or (b <> 0))); 252 V8 := ab_v8[2 * b + b + a]; 253 end; 254 255 procedure V8_to_ab(V8: integer; var a, b: integer); 256 begin 257 a := v8_a[V8]; 258 b := v8_b[V8]; 259 end; 260 261 procedure ab_to_V21(a, b: integer; var V21: integer); 262 begin 263 V21 := (a + b + 3) shl 2 + (a - b + 3) shr 1; 264 end; 265 266 procedure V21_to_ab(V21: integer; var a, b: integer); 267 var 268 dx, dy: integer; 269 begin 270 dy := V21 shr 2 - 3; 271 dx := V21 and 3 shl 1 - 3 + (dy + 3) and 1; 272 a := (dx + dy) div 2; 273 b := (dy - dx) div 2; 236 procedure ab_to_V8(a,b: integer; var V8: integer); 237 begin 238 assert((abs(a)<=1) and (abs(b)<=1) and ((a<>0) or (b<>0))); 239 V8:=ab_v8[2*b+b+a]; 240 end; 241 242 procedure V8_to_ab(V8: integer; var a,b: integer); 243 begin 244 a:=v8_a[V8]; b:=V8_b[V8]; 245 end; 246 247 procedure ab_to_V21(a,b: integer; var V21: integer); 248 begin 249 V21:=(a+b+3) shl 2+(a-b+3) shr 1; 250 end; 251 252 procedure V21_to_ab(V21: integer; var a,b: integer); 253 var 254 dx,dy: integer; 255 begin 256 dy:=V21 shr 2-3; 257 dx:=V21 and 3 shl 1 -3 + (dy+3) and 1; 258 a:=(dx+dy) div 2; 259 b:=(dy-dx) div 2; 274 260 end; 275 261 276 262 procedure V8_to_Loc(Loc0: integer; var VicinityLoc: TVicinity8Loc); 277 263 var 278 x0, y0,lx: integer;279 begin 280 lx :=G.lx;281 y0 := cardinal(Loc0) *decompose24 shr 24;282 x0 := Loc0 - y0 *lx; // Loc0 mod lx;283 VicinityLoc[1] := Loc0 + lx *2;284 VicinityLoc[3] := Loc0 -1;285 VicinityLoc[5] := Loc0 - lx *2;286 VicinityLoc[7] := Loc0 +1;287 inc(Loc0,y0 and 1);288 VicinityLoc[0] := Loc0 +lx;289 VicinityLoc[2] := Loc0 + lx -1;290 VicinityLoc[4] := Loc0 - lx -1;291 VicinityLoc[6] := Loc0 -lx;292 293 // world is round!294 if x0 < lx -1 then264 x0,y0,lx: integer; 265 begin 266 lx:=G.lx; 267 y0:=cardinal(Loc0)*decompose24 shr 24; 268 x0:=Loc0-y0*lx; // Loc0 mod lx; 269 VicinityLoc[1]:=Loc0+lx*2; 270 VicinityLoc[3]:=Loc0-1; 271 VicinityLoc[5]:=Loc0-lx*2; 272 VicinityLoc[7]:=Loc0+1; 273 inc(Loc0,y0 and 1); 274 VicinityLoc[0]:=Loc0+lx; 275 VicinityLoc[2]:=Loc0+lx-1; 276 VicinityLoc[4]:=Loc0-lx-1; 277 VicinityLoc[6]:=Loc0-lx; 278 279 // world is round! 280 if x0<lx-1 then 295 281 begin 296 if x0 =0 then282 if x0=0 then 297 283 begin 298 inc(VicinityLoc[3],lx);299 if y0 and 1 =0 then284 inc(VicinityLoc[3],lx); 285 if y0 and 1=0 then 300 286 begin 301 inc(VicinityLoc[2],lx);302 inc(VicinityLoc[4],lx);287 inc(VicinityLoc[2],lx); 288 inc(VicinityLoc[4],lx); 303 289 end 304 290 end 305 291 end 306 else292 else 307 293 begin 308 dec(VicinityLoc[7],lx);309 if y0 and 1 =1 then294 dec(VicinityLoc[7],lx); 295 if y0 and 1=1 then 310 296 begin 311 dec(VicinityLoc[0],lx);312 dec(VicinityLoc[6],lx);297 dec(VicinityLoc[0],lx); 298 dec(VicinityLoc[6],lx); 313 299 end 314 300 end; 315 301 316 // check south pole 317 case G.ly - y0 of 318 1: 302 // check south pole 303 case G.ly-y0 of 304 1: 305 begin 306 VicinityLoc[0]:=-$1000; 307 VicinityLoc[1]:=-$1000; 308 VicinityLoc[2]:=-$1000; 309 end; 310 2: VicinityLoc[1]:=-$1000; 311 end 312 end; 313 314 procedure V21_to_Loc(Loc0: integer; var VicinityLoc: TVicinity21Loc); 315 var 316 dx,dy,bit,y0,xComp,yComp,xComp0,xCompSwitch: integer; 317 dst: ^integer; 318 begin 319 y0:=cardinal(Loc0)*decompose24 shr 24; 320 xComp0:=Loc0-y0*G.lx-1; // Loc0 mod G.lx -1 321 xCompSwitch:=xComp0-1+y0 and 1; 322 if xComp0<0 then inc(xComp0,G.lx); 323 if xCompSwitch<0 then inc(xCompSwitch,G.lx); 324 xCompSwitch:=xCompSwitch xor xComp0; 325 yComp:=G.lx*(y0-3); 326 dst:=@VicinityLoc; 327 bit:=1; 328 for dy:=0 to 6 do 329 if yComp<MapSize then 330 begin 331 xComp0:=xComp0 xor xCompSwitch; 332 xComp:=xComp0; 333 for dx:=0 to 3 do 319 334 begin 320 VicinityLoc[0] := -$1000; 321 VicinityLoc[1] := -$1000; 322 VicinityLoc[2] := -$1000; 335 if bit and $67F7F76<>0 then dst^:=xComp+yComp 336 else dst^:=-1; 337 inc(xComp); 338 if xComp>=G.lx then dec(xComp, G.lx); 339 inc(dst); 340 bit:=bit shl 1; 323 341 end; 324 2: 325 VicinityLoc[1] := -$1000; 326 end 327 end; 328 329 procedure V21_to_Loc(Loc0: integer; var VicinityLoc: TVicinity21Loc); 330 var 331 dx, dy, bit, y0, xComp, yComp, xComp0, xCompSwitch: integer; 332 dst: ^integer; 333 begin 334 y0 := cardinal(Loc0) * decompose24 shr 24; 335 xComp0 := Loc0 - y0 * G.lx - 1; // Loc0 mod G.lx -1 336 xCompSwitch := xComp0 - 1 + y0 and 1; 337 if xComp0 < 0 then 338 inc(xComp0, G.lx); 339 if xCompSwitch < 0 then 340 inc(xCompSwitch, G.lx); 341 xCompSwitch := xCompSwitch xor xComp0; 342 yComp := G.lx * (y0 - 3); 343 dst := @VicinityLoc; 344 bit := 1; 345 for dy := 0 to 6 do 346 if yComp < MapSize then 342 inc(yComp,G.lx); 343 end 344 else 347 345 begin 348 xComp0 := xComp0 xor xCompSwitch; 349 xComp := xComp0; 350 for dx := 0 to 3 do 346 for dx:=0 to 3 do 347 begin dst^:=-$1000; inc(dst); end; 348 end 349 end; 350 351 function Distance(Loc0,Loc1: integer): integer; 352 var 353 a,b,dx,dy: integer; 354 begin 355 Loc_to_ab(Loc0,Loc1,a,b); 356 dx:=abs(a-b); 357 dy:=abs(a+b); 358 result:=dx+dy+abs(dx-dy) shr 1; 359 end; 360 361 362 procedure Init(NewGameData: TNewGameData); 363 {$IFDEF DEBUG}var Loc: integer;{$ENDIF} 364 begin 365 G:=NewGameData; 366 MapSize:=G.lx*G.ly; 367 decompose24:=(1 shl 24-1) div G.lx +1; 368 {$IFDEF DEBUG}for Loc:=0 to MapSize-1 do assert(cardinal(Loc)*decompose24 shr 24=cardinal(Loc div G.lx));{$ENDIF} 369 end; 370 371 372 constructor TCustomAI.Create(Nation: integer); 373 begin 374 inherited Create; 375 me:=Nation; 376 RO:=pointer(G.RO[Nation]); 377 Map:=pointer(RO.Map); 378 MyUnit:=pointer(RO.Un); 379 MyCity:=pointer(RO.City); 380 MyModel:=pointer(RO.Model); 381 Opponent:=-1; 382 end; 383 384 destructor TCustomAI.Destroy; 385 begin 386 Server(sSetDebugMap,me,0,nodata^); 387 end; 388 389 390 procedure TCustomAI.Process(Command: integer; var Data); 391 var 392 Nation,NewResearch,NewGov,count,ad,cix,iix: integer; 393 NegoTime: TNegoTime; 394 begin 395 case Command of 396 cTurn, cContinue: 397 begin 398 if RO.Alive and (1 shl me)=0 then 399 begin // I'm dead, huhu 400 Server(sTurn,me,0,nodata^); 401 exit 402 end; 403 if Command=cTurn then 351 404 begin 352 if bit and $67F7F76 <> 0 then 353 dst^ := xComp + yComp 354 else 355 dst^ := -1; 356 inc(xComp); 357 if xComp >= G.lx then 358 dec(xComp, G.lx); 359 inc(dst); 360 bit := bit shl 1; 405 fillchar(cixStateImp, sizeof(cixStateImp), $FF); 406 for cix:=0 to RO.nCity-1 do if MyCity[cix].Loc>=0 then 407 for iix:=imPalace to imSpacePort do 408 if MyCity[cix].Built[iix]>0 then 409 cixStateImp[iix]:=cix; 410 if RO.Happened and phChangeGov<>0 then 411 begin 412 NewGov:=ChooseGovernment; 413 if NewGov>gAnarchy then 414 Server(sSetGovernment,me,NewGov,nodata^); 415 end; 416 HaveTurned:=false; 417 Contacted:=[]; 361 418 end; 362 inc(yComp, G.lx); 363 end 419 if (Command=cContinue) and (MyAction=scContact) then 420 begin 421 if OnNegoRejected_CancelTreaty then 422 if RO.Treaty[Opponent]>=trPeace then 423 if Server(sCancelTreaty,me,0,nodata^)<rExecuted then 424 assert(false) 425 end 426 else UnwantedNego:=[]; 427 Opponent:=-1; 428 repeat 429 if HaveTurned then NegoTime:=EndOfTurn 430 else NegoTime:=BeginOfTurn; 431 if RO.Government<>gAnarchy then 432 for Nation:=0 to nPl-1 do 433 if (Nation<>me) and (1 shl Nation and RO.Alive<>0) 434 and (RO.Treaty[Nation]>=trNone) 435 and not (Nation in Contacted) and not (Nation in UnwantedNego) 436 and (Server(scContact-sExecute + Nation shl 4, me, 0, nodata^)>=rExecuted) then 437 if WantNegotiation(Nation, NegoTime) then 438 begin 439 if Server(scContact + Nation shl 4, me, 0, nodata^)>=rExecuted then 440 begin 441 include(Contacted, Nation); 442 Opponent:=Nation; 443 MyAction:=scContact; 444 exit; 445 end; 446 end 447 else include(UnwantedNego,Nation); 448 if NegoTime=BeginOfTurn then 449 begin 450 DoTurn; 451 HaveTurned:=true; 452 Contacted:=[]; 453 UnwantedNego:=[]; 454 end 455 else break; 456 until false; 457 if RO.Happened and phTech<>0 then 458 begin 459 NewResearch:=ChooseResearchAdvance; 460 if NewResearch<0 then 461 begin // choose random research 462 count:=0; 463 for ad:=0 to nAdv-1 do if AdvanceResearchable(ad) then 464 begin inc(count); if random(count)=0 then NewResearch:=ad end 465 end; 466 Server(sSetResearch,me,NewResearch,nodata^) 467 end; 468 if Server(sTurn,me,0,nodata^)<rExecuted then 469 assert(false); 470 end; 471 scContact: 472 if WantNegotiation(integer(Data), EnemyCalled) then 473 begin 474 if Server(scDipStart, me, 0, nodata^)<rExecuted then 475 assert(false); 476 Opponent:=integer(Data); 477 MyAction:=scDipStart; 478 end 364 479 else 480 begin 481 if Server(scReject, me, 0, nodata^)<rExecuted then 482 assert(false); 483 end; 484 scDipStart, scDipNotice, scDipAccept, scDipCancelTreaty, scDipOffer, scDipBreak: 365 485 begin 366 for dx := 0 to 3 do 486 OppoAction:=Command; 487 if Command=scDipOffer then OppoOffer:=TOffer(Data); 488 if Command=scDipStart then 489 MyLastAction:=scContact 490 else 367 491 begin 368 dst^ := -$1000;369 inc(dst);492 MyLastAction:=MyAction; 493 MyLastOffer:=MyOffer; 370 494 end; 371 end 372 end; 373 374 procedure Init(NewGameData: TNewGameData); 375 {$IFDEF DEBUG}var 376 Loc: integer; {$ENDIF} 377 begin 378 G := NewGameData; 379 MapSize := G.lx * G.ly; 380 decompose24 := (1 shl 24 - 1) div G.lx + 1; 381 {$IFDEF DEBUG} for Loc := 0 to MapSize - 1 do 382 assert(cardinal(Loc) * decompose24 shr 24 = cardinal(Loc div G.lx)); 383 {$ENDIF} 384 end; 385 386 constructor TCustomAI.Create(Nation: integer); 387 begin 388 inherited Create; 389 me := Nation; 390 RO := pointer(G.RO[Nation]); 391 Map := pointer(RO.Map); 392 MyUnit := pointer(RO.Un); 393 MyCity := pointer(RO.City); 394 MyModel := pointer(RO.Model); 395 Opponent := -1; 396 end; 397 398 destructor TCustomAI.Destroy; 399 begin 400 Server(sSetDebugMap, me, 0, nodata^); 401 end; 402 403 procedure TCustomAI.Process(Command: integer; var Data); 404 var 405 Nation, NewResearch, NewGov, Count, ad, cix, iix: integer; 406 NegoTime: TNegoTime; 407 begin 408 case Command of 409 cTurn, cContinue: 410 begin 411 if RO.Alive and (1 shl me) = 0 then 412 begin // I'm dead, huhu 413 Server(sTurn, me, 0, nodata^); 414 exit 415 end; 416 if Command = cTurn then 417 begin 418 fillchar(cixStateImp, sizeof(cixStateImp), $FF); 419 for cix := 0 to RO.nCity - 1 do 420 if MyCity[cix].Loc >= 0 then 421 for iix := imPalace to imSpacePort do 422 if MyCity[cix].Built[iix] > 0 then 423 cixStateImp[iix] := cix; 424 if RO.Happened and phChangeGov <> 0 then 425 begin 426 NewGov := ChooseGovernment; 427 if NewGov > gAnarchy then 428 Server(sSetGovernment, me, NewGov, nodata^); 429 end; 430 HaveTurned := false; 431 Contacted := []; 432 end; 433 if (Command = cContinue) and (MyAction = scContact) then 434 begin 435 if OnNegoRejected_CancelTreaty then 436 if RO.Treaty[Opponent] >= trPeace then 437 if Server(sCancelTreaty, me, 0, nodata^) < rExecuted then 438 assert(false) 439 end 440 else 441 UnwantedNego := []; 442 Opponent := -1; 443 repeat 444 if HaveTurned then 445 NegoTime := EndOfTurn 446 else 447 NegoTime := BeginOfTurn; 448 if RO.Government <> gAnarchy then 449 for Nation := 0 to nPl - 1 do 450 if (Nation <> me) and (1 shl Nation and RO.Alive <> 0) and 451 (RO.Treaty[Nation] >= trNone) and not(Nation in Contacted) and 452 not(Nation in UnwantedNego) and 453 (Server(scContact - sExecute + Nation shl 4, me, 0, nodata^) >= 454 rExecuted) then 455 if WantNegotiation(Nation, NegoTime) then 456 begin 457 if Server(scContact + Nation shl 4, me, 0, nodata^) >= rExecuted 458 then 459 begin 460 include(Contacted, Nation); 461 Opponent := Nation; 462 MyAction := scContact; 463 exit; 464 end; 465 end 466 else 467 include(UnwantedNego, Nation); 468 if NegoTime = BeginOfTurn then 469 begin 470 DoTurn; 471 HaveTurned := true; 472 Contacted := []; 473 UnwantedNego := []; 474 end 475 else 476 break; 477 until false; 478 if RO.Happened and phTech <> 0 then 479 begin 480 NewResearch := ChooseResearchAdvance; 481 if NewResearch < 0 then 482 begin // choose random research 483 Count := 0; 484 for ad := 0 to nAdv - 1 do 485 if AdvanceResearchable(ad) then 486 begin 487 inc(Count); 488 if random(Count) = 0 then 489 NewResearch := ad 490 end 491 end; 492 Server(sSetResearch, me, NewResearch, nodata^) 493 end; 494 if Server(sTurn, me, 0, nodata^) < rExecuted then 495 assert(false); 496 end; 497 scContact: 498 if WantNegotiation(integer(Data), EnemyCalled) then 499 begin 500 if Server(scDipStart, me, 0, nodata^) < rExecuted then 501 assert(false); 502 Opponent := integer(Data); 503 MyAction := scDipStart; 504 end 505 else 506 begin 507 if Server(scReject, me, 0, nodata^) < rExecuted then 508 assert(false); 509 end; 510 scDipStart, scDipNotice, scDipAccept, scDipCancelTreaty, scDipOffer, 511 scDipBreak: 512 begin 513 OppoAction := Command; 514 if Command = scDipOffer then 515 OppoOffer := TOffer(Data); 516 if Command = scDipStart then 517 MyLastAction := scContact 518 else 519 begin 520 MyLastAction := MyAction; 521 MyLastOffer := MyOffer; 522 end; 523 if (OppoAction = scDipCancelTreaty) or (OppoAction = scDipBreak) then 524 MyAction := scDipNotice 525 else 526 begin 527 MyAction := scDipOffer; 528 MyOffer.nDeliver := 0; 529 MyOffer.nCost := 0; 530 end; 531 DoNegotiation; 532 assert((MyAction = scDipNotice) or (MyAction = scDipAccept) or 533 (MyAction = scDipCancelTreaty) or (MyAction = scDipOffer) or 534 (MyAction = scDipBreak)); 535 if MyAction = scDipOffer then 536 Server(MyAction, me, 0, MyOffer) 537 else 538 Server(MyAction, me, 0, nodata^); 539 end; 540 cShowEndContact: 541 Opponent := -1; 495 if (OppoAction=scDipCancelTreaty) or (OppoAction=scDipBreak) then 496 MyAction:=scDipNotice 497 else begin MyAction:=scDipOffer; MyOffer.nDeliver:=0; MyOffer.nCost:=0; end; 498 DoNegotiation; 499 assert((MyAction=scDipNotice) or (MyAction=scDipAccept) 500 or (MyAction=scDipCancelTreaty) or (MyAction=scDipOffer) 501 or (MyAction=scDipBreak)); 502 if MyAction=scDipOffer then Server(MyAction, me, 0, MyOffer) 503 else Server(MyAction, me, 0, nodata^); 504 end; 505 cShowEndContact: 506 Opponent:=-1; 542 507 end; 543 508 end; 544 509 545 510 {$HINTS OFF} 546 547 511 procedure TCustomAI.SetDataDefaults; 548 512 begin … … 561 525 end; 562 526 563 procedure TCustomAI.OnBeforeEnemyAttack(UnitInfo: TUnitInfo; 564 ToLoc, EndHealth,EndHealthDef: integer);527 procedure TCustomAI.OnBeforeEnemyAttack(UnitInfo: TUnitInfo; ToLoc, EndHealth, 528 EndHealthDef: integer); 565 529 begin 566 530 end; … … 580 544 function TCustomAI.ChooseResearchAdvance: integer; 581 545 begin 582 result :=-1546 result:=-1 583 547 end; 584 548 585 549 function TCustomAI.ChooseStealAdvance: integer; 586 550 begin 587 result :=-1551 result:=-1 588 552 end; 589 553 590 554 function TCustomAI.ChooseGovernment: integer; 591 555 begin 592 result := gDespotism 593 end; 594 595 function TCustomAI.WantNegotiation(Nation: integer; 596 NegoTime: TNegoTime): boolean; 597 begin 598 result := false; 556 result:=gDespotism 557 end; 558 559 function TCustomAI.WantNegotiation(Nation: integer; NegoTime: TNegoTime): boolean; 560 begin 561 result:=false; 599 562 end; 600 563 601 564 function TCustomAI.OnNegoRejected_CancelTreaty: boolean; 602 565 begin 603 result :=false;566 result:=false; 604 567 end; 605 568 {$HINTS ON} … … 607 570 procedure TCustomAI.StealAdvance; 608 571 var 609 Steal, ad, Count: integer;610 begin 611 Steal :=ChooseStealAdvance;612 if Steal <0 then572 Steal, ad, count: integer; 573 begin 574 Steal:=ChooseStealAdvance; 575 if Steal<0 then 613 576 begin // choose random advance 614 Count := 0; 615 for ad := 0 to nAdv - 1 do 616 if AdvanceStealable(ad) then 617 begin 618 inc(Count); 619 if random(Count) = 0 then 620 Steal := ad 621 end 577 count:=0; 578 for ad:=0 to nAdv-1 do if AdvanceStealable(ad) then 579 begin inc(count); if random(count)=0 then Steal:=ad end 622 580 end; 623 if Steal >= 0 then 624 Server(sStealTech, me, Steal, nodata^); 625 RO.Happened := RO.Happened and not phStealTech 581 if Steal>=0 then Server(sStealTech,me,Steal,nodata^); 582 RO.Happened:=RO.Happened and not phStealTech 626 583 end; 627 584 628 585 function TCustomAI.IsResearched(Advance: integer): boolean; 629 586 begin 630 result := RO.Tech[Advance] >= tsApplicable 587 result:= (Advance=preNone) 588 or (Advance<>preNA) and (RO.Tech[Advance]>=tsApplicable) 631 589 end; 632 590 633 591 function TCustomAI.ResearchCost: integer; 634 592 begin 635 Server(sGetTechCost, me, 0,result)593 Server(sGetTechCost,me,0,result) 636 594 end; 637 595 638 596 function TCustomAI.ChangeAttitude(Nation, Attitude: integer): integer; 639 597 begin 640 result := Server(sSetAttitude + Nation shl 4, me, Attitude,nodata^)598 result:=Server(sSetAttitude+Nation shl 4,me,Attitude,nodata^) 641 599 end; 642 600 643 601 function TCustomAI.Revolution: integer; 644 602 begin 645 result := Server(sRevolution, me, 0, nodata^); 646 end; 647 648 function TCustomAI.ChangeRates(Tax, Lux: integer): integer; 649 begin 650 result := Server(sSetRates, me, Tax div 10 and $F + Lux div 10 and 651 $F shl 4, nodata^) 603 result:=Server(sRevolution,me,0,nodata^); 604 end; 605 606 function TCustomAI.ChangeRates(Tax,Lux: integer): integer; 607 begin 608 result:=Server(sSetRates,me,Tax div 10 and $f+Lux div 10 and $f shl 4,nodata^) 652 609 end; 653 610 654 611 function TCustomAI.PrepareNewModel(Domain: integer): integer; 655 612 begin 656 result := Server(sCreateDevModel, me, Domain,nodata^);613 result:=Server(sCreateDevModel,me,Domain,nodata^); 657 614 end; 658 615 659 616 function TCustomAI.SetNewModelFeature(F, Count: integer): integer; 660 617 begin 661 result := Server(sSetDevModelCap + Count shl 4, me, F,nodata^)618 result:=Server(sSetDevModelCap+Count shl 4,me,F,nodata^) 662 619 end; 663 620 664 621 function TCustomAI.AdvanceResearchable(Advance: integer): boolean; 665 622 begin 666 result := Server(sSetResearch - sExecute, me, Advance, nodata^) >=rExecuted;623 result:= Server(sSetResearch-sExecute,me,Advance,nodata^)>=rExecuted; 667 624 end; 668 625 669 626 function TCustomAI.AdvanceStealable(Advance: integer): boolean; 670 627 begin 671 result := Server(sStealTech - sExecute, me, Advance, nodata^) >= rExecuted; 672 end; 673 674 function TCustomAI.GetJobProgress(Loc: integer; 675 var JobProgress: TJobProgressData): boolean; 676 begin 677 result := Server(sGetJobProgress, me, Loc, JobProgress) >= rExecuted; 628 result:= Server(sStealTech-sExecute,me,Advance,nodata^)>=rExecuted; 629 end; 630 631 function TCustomAI.GetJobProgress(Loc: integer; var JobProgress: TJobProgressData): boolean; 632 begin 633 result:= Server(sGetJobProgress,me,Loc,JobProgress)>=rExecuted; 678 634 end; 679 635 680 636 function TCustomAI.DebugMessage(Level: integer; Text: string): boolean; 681 637 begin 682 Text := copy('P' + char(48 + me) + ' ' + Text, 1,254);683 Server(sMessage, me, Level,pchar(Text)^);684 685 result :=true;638 Text:=copy('P'+char(48+me)+' '+Text,1,254); 639 Server(sMessage,me,Level,pchar(Text)^); 640 641 result:=true; 686 642 // always returns true so that it can be used like 687 643 // "assert(DebugMessage(...));" -> not compiled in release build … … 690 646 function TCustomAI.SetDebugMap(var DebugMap): boolean; 691 647 begin 692 Server(sSetDebugMap, me, 0, DebugMap);693 694 result :=true;648 Server(sSetDebugMap, me, 0, DebugMap); 649 650 result:=true; 695 651 // always returns true so that it can be used like 696 652 // "assert(SetDebugMap(...));" -> not compiled in release build … … 699 655 procedure TCustomAI.Unit_FindMyDefender(Loc: integer; var uix: integer); 700 656 begin 701 if Server(sGetDefender, me, Loc, uix) < rExecuted then 702 uix := -1 657 if Server(sGetDefender,me,Loc,uix)<rExecuted then uix:=-1 703 658 end; 704 659 705 660 procedure TCustomAI.Unit_FindEnemyDefender(Loc: integer; var euix: integer); 706 661 begin 707 euix := RO.nEnemyUn - 1; 708 while (euix >= 0) and (RO.EnemyUn[euix].Loc <> Loc) do 709 dec(euix); 710 end; 711 712 function TCustomAI.Unit_Move(uix, ToLoc: integer): integer; 713 var 714 Step: integer; 715 DestinationReached: boolean; 716 Advice: TMoveAdviceData; 717 begin 718 assert((uix >= 0) and (uix < RO.nUn) and (MyUnit[uix].Loc >= 0)); // is a unit 719 { Loc_to_ab(MyUnit[uix].Loc,ToLoc,a,b); 720 assert((a<>0) or (b<>0)); 721 if (a>=-1) and (a<=1) and (b>=-1) and (b<=1) then 722 begin // move to adjacent tile 723 !!!problem: if move is invalid, return codes are not consistent with other branch (eNoWay) 724 Advice.nStep:=1; 725 Advice.dx[0]:=a-b; 726 Advice.dy[0]:=a+b; 727 Advice.MoreTurns:=0; 728 Advice.MaxHostile_MovementLeft:=MyUnit[uix].Movement; 729 result:=eOK; 662 euix:=RO.nEnemyUn-1; 663 while (euix>=0) and (RO.EnemyUn[euix].Loc<>Loc) do 664 dec(euix); 665 end; 666 667 function TCustomAI.Unit_Move(uix,ToLoc: integer): integer; 668 var 669 Step: integer; 670 DestinationReached: boolean; 671 Advice: TMoveAdviceData; 672 begin 673 assert((uix>=0) and (uix<RO.nUn) and (MyUnit[uix].Loc>=0)); // is a unit 674 {Loc_to_ab(MyUnit[uix].Loc,ToLoc,a,b); 675 assert((a<>0) or (b<>0)); 676 if (a>=-1) and (a<=1) and (b>=-1) and (b<=1) then 677 begin // move to adjacent tile 678 !!!problem: if move is invalid, return codes are not consistent with other branch (eNoWay) 679 Advice.nStep:=1; 680 Advice.dx[0]:=a-b; 681 Advice.dy[0]:=a+b; 682 Advice.MoreTurns:=0; 683 Advice.MaxHostile_MovementLeft:=MyUnit[uix].Movement; 684 result:=eOK; 685 end 686 else} 687 begin // move to non-adjacent tile, find shortest path 688 Advice.ToLoc:=ToLoc; 689 Advice.MoreTurns:=9999; 690 Advice.MaxHostile_MovementLeft:=100; 691 result:=Server(sGetMoveAdvice,me,uix,Advice); 692 end; 693 if result=eOk then 694 begin 695 DestinationReached:=false; 696 Step:=0; 697 repeat 698 if result and (rExecuted or rUnitRemoved)=rExecuted then // check if destination reached 699 if (ToLoc>=0) and (Advice.MoreTurns=0) and (Step=Advice.nStep-1) 700 and ((Map[ToLoc] and (fUnit or fOwned)=fUnit) // attack 701 or (Map[ToLoc] and (fCity or fOwned)=fCity) 702 and ((MyModel[MyUnit[uix].mix].Domain<>dGround) // bombardment 703 or (MyModel[MyUnit[uix].mix].Flags and mdCivil<>0))) then // can't capture 704 begin DestinationReached:=true; break end // stop next to destination 705 else if Step=Advice.nStep then 706 DestinationReached:=true; // normal move -- stop at destination 707 708 if (Step=Advice.nStep) or (result<>eOK) and (result<>eLoaded) then 709 break; 710 711 result:=Server(sMoveUnit+(Advice.dx[Step] and 7) shl 4 +(Advice.dy[Step] and 7) shl 7, 712 me,uix,nodata^); 713 inc(Step); 714 if RO.Happened and phStealTech<>0 then StealAdvance; 715 until false; 716 if DestinationReached then 717 if Advice.nStep=25 then 718 result:=Unit_Move(uix,ToLoc) // Shinkansen 719 else if Advice.MoreTurns=0 then 720 result:=result or rLocationReached 721 else result:=result or rMoreTurns; 722 end 723 end; 724 725 function TCustomAI.Unit_Step(uix,ToLoc: integer): integer; 726 var 727 a,b: integer; 728 begin 729 Loc_to_ab(MyUnit[uix].Loc, ToLoc, a, b); 730 assert(((a<>0) or (b<>0)) and (a>=-1) and (a<=1) and (b>=-1) and (b<=1)); 731 result:=Server(sMoveUnit+((a-b) and 7) shl 4 +((a+b) and 7) shl 7, me, uix, nodata^); 732 if RO.Happened and phStealTech<>0 then StealAdvance; 733 end; 734 735 function TCustomAI.Unit_Attack(uix,ToLoc: integer): integer; 736 var 737 a,b: integer; 738 begin 739 assert((uix>=0) and (uix<RO.nUn) and (MyUnit[uix].Loc>=0) // is a unit 740 and ((Map[ToLoc] and (fUnit or fOwned)=fUnit) // is an attack 741 or (Map[ToLoc] and (fCity or fOwned)=fCity) 742 and (MyModel[MyUnit[uix].mix].Domain<>dGround))); // is a bombardment 743 Loc_to_ab(MyUnit[uix].Loc,ToLoc,a,b); 744 assert(((a<>0) or (b<>0)) and (a>=-1) and (a<=1) and (b>=-1) and (b<=1)); // attack to adjacent tile 745 result:=Server(sMoveUnit+(a-b) and 7 shl 4 +(a+b) and 7 shl 7,me,uix,nodata^); 746 end; 747 748 function TCustomAI.Unit_DoMission(uix,MissionType,ToLoc: integer): integer; 749 var 750 a,b: integer; 751 begin 752 result:=Server(sSetSpyMission + MissionType shl 4,me,0,nodata^); 753 if result>=rExecuted then 754 begin 755 assert((uix>=0) and (uix<RO.nUn) and (MyUnit[uix].Loc>=0) // is a unit 756 and (MyModel[MyUnit[uix].mix].Kind=mkDiplomat)); // is a commando 757 Loc_to_ab(MyUnit[uix].Loc,ToLoc,a,b); 758 assert(((a<>0) or (b<>0)) and (a>=-1) and (a<=1) and (b>=-1) and (b<=1)); // city must be adjacent 759 result:=Server(sMoveUnit-sExecute+(a-b) and 7 shl 4 +(a+b) and 7 shl 7,me,uix,nodata^); 760 if result=eMissionDone then 761 result:=Server(sMoveUnit+(a-b) and 7 shl 4 +(a+b) and 7 shl 7,me,uix,nodata^) 762 else if (result<>eNoTime_Move) and (result<>eTreaty) and (result<>eNoTurn) then 763 result:=eInvalid // not a special commando mission! 764 end 765 end; 766 767 function TCustomAI.Unit_MoveForecast(uix,ToLoc: integer; 768 var RemainingMovement: integer): boolean; 769 var 770 Advice: TMoveAdviceData; 771 begin 772 assert((uix>=0) and (uix<RO.nUn) and (MyUnit[uix].Loc>=0)); // is a unit 773 Advice.ToLoc:=ToLoc; 774 Advice.MoreTurns:=0; 775 Advice.MaxHostile_MovementLeft:=100; 776 if Server(sGetMoveAdvice,me,uix,Advice)=eOk then 777 begin 778 RemainingMovement:=Advice.MaxHostile_MovementLeft; 779 result:=true 780 end 781 else 782 begin 783 RemainingMovement:=-1; 784 result:=false 785 end 786 end; 787 788 // negative RemainingHealth is remaining helth of defender if lost 789 function TCustomAI.Unit_AttackForecast(uix,ToLoc,AttackMovement: integer; 790 var RemainingHealth: integer): boolean; 791 var 792 BattleForecast: TBattleForecast; 793 begin 794 assert((uix>=0) and (uix<RO.nUn) and (MyUnit[uix].Loc>=0) // is a unit 795 and (Map[ToLoc] and (fUnit or fOwned)=fUnit)); // is an attack 796 RemainingHealth:=-$100; 797 result:=false; 798 if AttackMovement>=0 then with MyUnit[uix] do 799 begin 800 BattleForecast.pAtt:=me; 801 BattleForecast.mixAtt:=mix; 802 BattleForecast.HealthAtt:=Health; 803 BattleForecast.ExpAtt:=Exp; 804 BattleForecast.FlagsAtt:=Flags; 805 BattleForecast.Movement:=AttackMovement; 806 if Server(sGetBattleForecast,me,ToLoc,BattleForecast)>=rExecuted then 807 begin 808 if BattleForecast.EndHealthAtt>0 then 809 RemainingHealth:=BattleForecast.EndHealthAtt 810 else RemainingHealth:=-BattleForecast.EndHealthDef; 811 result:=true 730 812 end 731 else } 732 begin // move to non-adjacent tile, find shortest path 733 Advice.ToLoc := ToLoc; 734 Advice.MoreTurns := 9999; 735 Advice.MaxHostile_MovementLeft := 100; 736 result := Server(sGetMoveAdvice, me, uix, Advice); 737 end; 738 if result = eOk then 813 end 814 end; 815 816 function TCustomAI.Unit_DefenseForecast(euix,ToLoc: integer; 817 var RemainingHealth: integer): boolean; 818 var 819 BattleForecast: TBattleForecast; 820 begin 821 assert((euix>=0) and (euix<RO.nEnemyUn) and (RO.EnemyUn[euix].Loc>=0) // is an enemy unit 822 and (Map[ToLoc] and (fUnit or fOwned)=(fUnit or fOwned))); // is an attack 823 RemainingHealth:=$100; 824 result:=false; 825 with RO.EnemyUn[euix] do 739 826 begin 740 DestinationReached := false; 741 Step := 0; 742 repeat 743 if result and (rExecuted or rUnitRemoved) = rExecuted then 744 // check if destination reached 745 if (ToLoc >= 0) and (Advice.MoreTurns = 0) and (Step = Advice.nStep - 1) 746 and ((Map[ToLoc] and (fUnit or fOwned) = fUnit) // attack 747 or (Map[ToLoc] and (fCity or fOwned) = fCity) and 748 ((MyModel[MyUnit[uix].mix].Domain <> dGround) // bombardment 749 or (MyModel[MyUnit[uix].mix].Flags and mdCivil <> 0))) then 750 // can't capture 751 begin 752 DestinationReached := true; 753 break 754 end // stop next to destination 755 else if Step = Advice.nStep then 756 DestinationReached := true; // normal move -- stop at destination 757 758 if (Step = Advice.nStep) or (result <> eOk) and (result <> eLoaded) then 759 break; 760 761 result := Server(sMoveUnit + (Advice.dx[Step] and 7) shl 4 + 762 (Advice.dy[Step] and 7) shl 7, me, uix, nodata^); 763 inc(Step); 764 if RO.Happened and phStealTech <> 0 then 765 StealAdvance; 766 until false; 767 if DestinationReached then 768 if Advice.nStep = 25 then 769 result := Unit_Move(uix, ToLoc) // Shinkansen 770 else if Advice.MoreTurns = 0 then 771 result := result or rLocationReached 772 else 773 result := result or rMoreTurns; 774 end 775 end; 776 777 function TCustomAI.Unit_Step(uix, ToLoc: integer): integer; 778 var 779 a, b: integer; 780 begin 781 Loc_to_ab(MyUnit[uix].Loc, ToLoc, a, b); 782 assert(((a <> 0) or (b <> 0)) and (a >= -1) and (a <= 1) and (b >= -1) and 783 (b <= 1)); 784 result := Server(sMoveUnit + ((a - b) and 7) shl 4 + ((a + b) and 7) shl 7, 785 me, uix, nodata^); 786 if RO.Happened and phStealTech <> 0 then 787 StealAdvance; 788 end; 789 790 function TCustomAI.Unit_Attack(uix, ToLoc: integer): integer; 791 var 792 a, b: integer; 793 begin 794 assert((uix >= 0) and (uix < RO.nUn) and (MyUnit[uix].Loc >= 0) // is a unit 795 and ((Map[ToLoc] and (fUnit or fOwned) = fUnit) // is an attack 796 or (Map[ToLoc] and (fCity or fOwned) = fCity) and 797 (MyModel[MyUnit[uix].mix].Domain <> dGround))); // is a bombardment 798 Loc_to_ab(MyUnit[uix].Loc, ToLoc, a, b); 799 assert(((a <> 0) or (b <> 0)) and (a >= -1) and (a <= 1) and (b >= -1) and 800 (b <= 1)); // attack to adjacent tile 801 result := Server(sMoveUnit + (a - b) and 7 shl 4 + (a + b) and 7 shl 7, me, 802 uix, nodata^); 803 end; 804 805 function TCustomAI.Unit_DoMission(uix, MissionType, ToLoc: integer): integer; 806 var 807 a, b: integer; 808 begin 809 result := Server(sSetSpyMission + MissionType shl 4, me, 0, nodata^); 810 if result >= rExecuted then 827 BattleForecast.pAtt:=Owner; 828 BattleForecast.mixAtt:=mix; 829 BattleForecast.HealthAtt:=Health; 830 BattleForecast.ExpAtt:=Exp; 831 BattleForecast.FlagsAtt:=Flags; 832 BattleForecast.Movement:=100; 833 if Server(sGetBattleForecast,me,ToLoc,BattleForecast)>=rExecuted then 834 begin 835 if BattleForecast.EndHealthDef>0 then 836 RemainingHealth:=BattleForecast.EndHealthDef 837 else RemainingHealth:=-BattleForecast.EndHealthAtt; 838 result:=true 839 end 840 end 841 end; 842 843 function TCustomAI.Unit_Disband(uix: integer): integer; 844 begin 845 result:=Server(sRemoveUnit,me,uix,nodata^) 846 end; 847 848 function TCustomAI.Unit_StartJob(uix,NewJob: integer): integer; 849 begin 850 result:=Server(sStartJob+NewJob shl 4,me,uix,nodata^) 851 end; 852 853 function TCustomAI.Unit_SetHomeHere(uix: integer): integer; 854 begin 855 result:=Server(sSetUnitHome,me,uix,nodata^) 856 end; 857 858 function TCustomAI.Unit_Load(uix: integer): integer; 859 begin 860 result:=Server(sLoadUnit,me,uix,nodata^) 861 end; 862 863 function TCustomAI.Unit_Unload(uix: integer): integer; 864 begin 865 result:=Server(sUnloadUnit,me,uix,nodata^) 866 end; 867 868 function TCustomAI.Unit_AddToCity(uix: integer): integer; 869 begin 870 result:=Server(sAddToCity,me,uix,nodata^) 871 end; 872 873 function TCustomAI.Unit_SelectTransport(uix: integer): integer; 874 begin 875 result:=Server(sSelectTransport,me,uix,nodata^) 876 end; 877 878 879 procedure TCustomAI.City_FindMyCity(Loc: integer; var cix: integer); 880 begin 881 if Map[Loc] and (fCity or fOwned)<>fCity or fOwned then 882 cix:=-1 883 else 811 884 begin 812 assert((uix >= 0) and (uix < RO.nUn) and (MyUnit[uix].Loc >= 0) // is a unit 813 and (MyModel[MyUnit[uix].mix].Kind = mkDiplomat)); // is a commando 814 Loc_to_ab(MyUnit[uix].Loc, ToLoc, a, b); 815 assert(((a <> 0) or (b <> 0)) and (a >= -1) and (a <= 1) and (b >= -1) and 816 (b <= 1)); // city must be adjacent 817 result := Server(sMoveUnit - sExecute + (a - b) and 7 shl 4 + (a + b) and 818 7 shl 7, me, uix, nodata^); 819 if result = eMissionDone then 820 result := Server(sMoveUnit + (a - b) and 7 shl 4 + (a + b) and 7 shl 7, 821 me, uix, nodata^) 822 else if (result <> eNoTime_Move) and (result <> eTreaty) and 823 (result <> eNoTurn) then 824 result := eInvalid // not a special commando mission! 825 end 826 end; 827 828 function TCustomAI.Unit_MoveForecast(uix, ToLoc: integer; 829 var RemainingMovement: integer): boolean; 830 var 831 Advice: TMoveAdviceData; 832 begin 833 assert((uix >= 0) and (uix < RO.nUn) and (MyUnit[uix].Loc >= 0)); // is a unit 834 Advice.ToLoc := ToLoc; 835 Advice.MoreTurns := 0; 836 Advice.MaxHostile_MovementLeft := 100; 837 if Server(sGetMoveAdvice, me, uix, Advice) = eOk then 885 cix:=RO.nCity-1; 886 while (cix>=0) and (MyCity[cix].Loc<>Loc) do 887 dec(cix); 888 end 889 end; 890 891 procedure TCustomAI.City_FindEnemyCity(Loc: integer; var ecix: integer); 892 begin 893 if Map[Loc] and (fCity or fOwned)<>fCity then 894 ecix:=-1 895 else 838 896 begin 839 RemainingMovement := Advice.MaxHostile_MovementLeft; 840 result := true 841 end 842 else 897 ecix:=RO.nEnemyCity-1; 898 while (ecix>=0) and (RO.EnemyCity[ecix].Loc<>Loc) do 899 dec(ecix); 900 end 901 end; 902 903 function TCustomAI.City_HasProject(cix: integer): boolean; 904 begin 905 result:= MyCity[cix].Project and (cpImp+cpIndex)<>cpImp+imTrGoods 906 end; 907 908 function TCustomAI.City_CurrentImprovementProject(cix: integer): integer; 909 begin 910 if MyCity[cix].Project and cpImp=0 then result:=-1 911 else 843 912 begin 844 RemainingMovement := -1; 845 result := false 846 end 847 end; 848 849 function TCustomAI.Unit_AttackForecast(uix, ToLoc, AttackMovement: integer; 850 var RemainingHealth: integer): boolean; 851 var 852 BattleForecast: TBattleForecast; 853 begin 854 assert((uix >= 0) and (uix < RO.nUn) and (MyUnit[uix].Loc >= 0) // is a unit 855 and (Map[ToLoc] and (fUnit or fOwned) = fUnit)); // is an attack 856 RemainingHealth := -$100; 857 result := false; 858 if AttackMovement >= 0 then 859 with MyUnit[uix] do 860 begin 861 BattleForecast.pAtt := me; 862 BattleForecast.mixAtt := mix; 863 BattleForecast.HealthAtt := Health; 864 BattleForecast.ExpAtt := Exp; 865 BattleForecast.FlagsAtt := Flags; 866 BattleForecast.Movement := AttackMovement; 867 if Server(sGetBattleForecast, me, ToLoc, BattleForecast) >= rExecuted then 868 begin 869 if BattleForecast.EndHealthAtt > 0 then 870 RemainingHealth := BattleForecast.EndHealthAtt 871 else 872 RemainingHealth := -BattleForecast.EndHealthDef; 873 result := true 874 end 875 end 876 end; 877 878 function TCustomAI.Unit_DefenseForecast(euix, ToLoc: integer; 879 var RemainingHealth: integer): boolean; 880 var 881 BattleForecast: TBattleForecast; 882 begin 883 assert((euix >= 0) and (euix < RO.nEnemyUn) and (RO.EnemyUn[euix].Loc >= 0) 884 // is an enemy unit 885 and (Map[ToLoc] and (fUnit or fOwned) = (fUnit or fOwned))); // is an attack 886 RemainingHealth := $100; 887 result := false; 888 with RO.EnemyUn[euix] do 889 begin 890 BattleForecast.pAtt := Owner; 891 BattleForecast.mixAtt := mix; 892 BattleForecast.HealthAtt := Health; 893 BattleForecast.ExpAtt := Exp; 894 BattleForecast.FlagsAtt := Flags; 895 BattleForecast.Movement := 100; 896 if Server(sGetBattleForecast, me, ToLoc, BattleForecast) >= rExecuted then 897 begin 898 if BattleForecast.EndHealthDef > 0 then 899 RemainingHealth := BattleForecast.EndHealthDef 900 else 901 RemainingHealth := -BattleForecast.EndHealthAtt; 902 result := true 903 end 904 end 905 end; 906 907 function TCustomAI.Unit_Disband(uix: integer): integer; 908 begin 909 result := Server(sRemoveUnit, me, uix, nodata^) 910 end; 911 912 function TCustomAI.Unit_StartJob(uix, NewJob: integer): integer; 913 begin 914 result := Server(sStartJob + NewJob shl 4, me, uix, nodata^) 915 end; 916 917 function TCustomAI.Unit_SetHomeHere(uix: integer): integer; 918 begin 919 result := Server(sSetUnitHome, me, uix, nodata^) 920 end; 921 922 function TCustomAI.Unit_Load(uix: integer): integer; 923 begin 924 result := Server(sLoadUnit, me, uix, nodata^) 925 end; 926 927 function TCustomAI.Unit_Unload(uix: integer): integer; 928 begin 929 result := Server(sUnloadUnit, me, uix, nodata^) 930 end; 931 932 function TCustomAI.Unit_AddToCity(uix: integer): integer; 933 begin 934 result := Server(sAddToCity, me, uix, nodata^) 935 end; 936 937 function TCustomAI.Unit_SelectTransport(uix: integer): integer; 938 begin 939 result := Server(sSelectTransport, me, uix, nodata^) 940 end; 941 942 procedure TCustomAI.City_FindMyCity(Loc: integer; var cix: integer); 943 begin 944 if Map[Loc] and (fCity or fOwned) <> fCity or fOwned then 945 cix := -1 946 else 947 begin 948 cix := RO.nCity - 1; 949 while (cix >= 0) and (MyCity[cix].Loc <> Loc) do 950 dec(cix); 951 end 952 end; 953 954 procedure TCustomAI.City_FindEnemyCity(Loc: integer; var ecix: integer); 955 begin 956 if Map[Loc] and (fCity or fOwned) <> fCity then 957 ecix := -1 958 else 959 begin 960 ecix := RO.nEnemyCity - 1; 961 while (ecix >= 0) and (RO.EnemyCity[ecix].Loc <> Loc) do 962 dec(ecix); 963 end 964 end; 965 966 function TCustomAI.City_HasProject(cix: integer): boolean; 967 begin 968 result := MyCity[cix].Project and (cpImp + cpIndex) <> cpImp + imTrGoods 969 end; 970 971 function TCustomAI.City_CurrentImprovementProject(cix: integer): integer; 972 begin 973 if MyCity[cix].Project and cpImp = 0 then 974 result := -1 975 else 976 begin 977 result := MyCity[cix].Project and cpIndex; 978 if result = imTrGoods then 979 result := -1 913 result:=MyCity[cix].Project and cpIndex; 914 if result=imTrGoods then result:=-1 980 915 end 981 916 end; … … 983 918 function TCustomAI.City_CurrentUnitProject(cix: integer): integer; 984 919 begin 985 if MyCity[cix].Project and cpImp <> 0 then 986 result := -1 987 else 988 result := MyCity[cix].Project and cpIndex; 989 end; 990 991 function TCustomAI.City_GetTileInfo(cix, TileLoc: integer; 992 var TileInfo: TTileInfo): integer; 993 begin 994 TileInfo.ExplCity := cix; 995 result := Server(sGetHypoCityTileInfo, me, TileLoc, TileInfo) 996 end; 997 998 function TCustomAI.City_GetReport(cix: integer; 999 var Report: TCityReport): integer; 1000 begin 1001 Report.HypoTiles := -1; 1002 Report.HypoTax := -1; 1003 Report.HypoLux := -1; 1004 result := Server(sGetCityReport, me, cix, Report) 920 if MyCity[cix].Project and cpImp<>0 then result:=-1 921 else result:=MyCity[cix].Project and cpIndex; 922 end; 923 924 function TCustomAI.City_GetTileInfo(cix,TileLoc: integer; var TileInfo: TTileInfo): integer; 925 begin 926 TileInfo.ExplCity:=cix; 927 result:=Server(sGetHypoCityTileInfo,me,TileLoc,TileInfo) 928 end; 929 930 function TCustomAI.City_GetReport(cix: integer; var Report: TCityReport): integer; 931 begin 932 Report.HypoTiles:=-1; 933 Report.HypoTax:=-1; 934 Report.HypoLux:=-1; 935 result:=Server(sGetCityReport,me,cix,Report) 1005 936 end; 1006 937 … … 1008 939 var Report: TCityReport): integer; 1009 940 begin 1010 Report.HypoTiles := HypoTiles; 1011 Report.HypoTax := HypoTax; 1012 Report.HypoLux := HypoLux; 1013 result := Server(sGetCityReport, me, cix, Report) 1014 end; 1015 1016 function TCustomAI.City_GetReportNew(cix: integer; 941 Report.HypoTiles:=HypoTiles; 942 Report.HypoTax:=HypoTax; 943 Report.HypoLux:=HypoLux; 944 result:=Server(sGetCityReport,me,cix,Report) 945 end; 946 947 function TCustomAI.City_GetReportNew(cix: integer; var Report: TCityReportNew): integer; 948 begin 949 Report.HypoTiles:=-1; 950 Report.HypoTaxRate:=-1; 951 Report.HypoLuxuryRate:=-1; 952 result:=Server(sGetCityReportNew,me,cix,Report) 953 end; 954 955 function TCustomAI.City_GetHypoReportNew(cix, HypoTiles, HypoTaxRate, HypoLuxuryRate: integer; 1017 956 var Report: TCityReportNew): integer; 1018 957 begin 1019 Report.HypoTiles := -1; 1020 Report.HypoTaxRate := -1; 1021 Report.HypoLuxuryRate := -1; 1022 result := Server(sGetCityReportNew, me, cix, Report) 1023 end; 1024 1025 function TCustomAI.City_GetHypoReportNew(cix, HypoTiles, HypoTaxRate, 1026 HypoLuxuryRate: integer; var Report: TCityReportNew): integer; 1027 begin 1028 Report.HypoTiles := HypoTiles; 1029 Report.HypoTaxRate := HypoTaxRate; 1030 Report.HypoLuxuryRate := HypoLuxuryRate; 1031 result := Server(sGetCityReportNew, me, cix, Report) 1032 end; 1033 1034 function TCustomAI.City_GetAreaInfo(cix: integer; 1035 var AreaInfo: TCityAreaInfo): integer; 1036 begin 1037 result := Server(sGetCityAreaInfo, me, cix, AreaInfo) 1038 end; 1039 1040 function TCustomAI.City_StartUnitProduction(cix, mix: integer): integer; 1041 begin 1042 result := Server(sSetCityProject, me, cix, mix) 1043 end; 1044 1045 function TCustomAI.City_StartEmigration(cix, mix: integer; 958 Report.HypoTiles:=HypoTiles; 959 Report.HypoTaxRate:=HypoTaxRate; 960 Report.HypoLuxuryRate:=HypoLuxuryRate; 961 result:=Server(sGetCityReportNew,me,cix,Report) 962 end; 963 964 function TCustomAI.City_GetAreaInfo(cix: integer; var AreaInfo: TCityAreaInfo): integer; 965 begin 966 result:=Server(sGetCityAreaInfo,me,cix,AreaInfo) 967 end; 968 969 function TCustomAI.City_StartUnitProduction(cix,mix: integer): integer; 970 begin 971 if (MyCity[cix].Project and (cpImp+cpIndex)<>mix) then 972 // not already producing that 973 result:=Server(sSetCityProject,me,cix,mix) 974 end; 975 976 function TCustomAI.City_StartEmigration(cix,mix: integer; 1046 977 AllowDisbandCity, AsConscripts: boolean): integer; 1047 978 var 1048 NewProject: integer; 1049 begin 1050 NewProject := mix; 1051 if AllowDisbandCity then 1052 NewProject := NewProject or cpDisbandCity; 1053 if AsConscripts then 1054 NewProject := NewProject or cpConscripts; 1055 result := Server(sSetCityProject, me, cix, NewProject) 1056 end; 1057 1058 function TCustomAI.City_StartImprovement(cix, iix: integer): integer; 1059 var 1060 NewProject: integer; 1061 begin 1062 NewProject := iix + cpImp; 1063 result := Server(sSetCityProject, me, cix, NewProject) 1064 end; 1065 1066 function TCustomAI.City_Improvable(cix, iix: integer): boolean; 1067 var 1068 NewProject: integer; 1069 begin 1070 NewProject := iix + cpImp; 1071 result := Server(sSetCityProject - sExecute, me, cix, NewProject) >= 1072 rExecuted; 979 NewProject: integer; 980 begin 981 NewProject:=mix; 982 if AllowDisbandCity then NewProject:=NewProject or cpDisbandCity; 983 if AsConscripts then NewProject:=NewProject or cpConscripts; 984 result:=Server(sSetCityProject,me,cix,NewProject) 985 end; 986 987 function TCustomAI.City_StartImprovement(cix,iix: integer): integer; 988 var 989 NewProject: integer; 990 begin 991 NewProject:=iix+cpImp; 992 if (MyCity[cix].Project and (cpImp+cpIndex)<>NewProject) then 993 // not already producing that 994 result:=Server(sSetCityProject,me,cix,NewProject) 995 end; 996 997 function TCustomAI.City_Improvable(cix,iix: integer): boolean; 998 var 999 NewProject: integer; 1000 begin 1001 NewProject:=iix+cpImp; 1002 result:= Server(sSetCityProject-sExecute,me,cix,NewProject)>=rExecuted; 1073 1003 end; 1074 1004 1075 1005 function TCustomAI.City_StopProduction(cix: integer): integer; 1076 1006 var 1077 NewProject: integer;1078 begin 1079 NewProject := imTrGoods +cpImp;1080 result := Server(sSetCityProject, me, cix,NewProject)1007 NewProject: integer; 1008 begin 1009 NewProject:=imTrGoods+cpImp; 1010 result:=Server(sSetCityProject,me,cix,NewProject) 1081 1011 end; 1082 1012 1083 1013 function TCustomAI.City_BuyProject(cix: integer): integer; 1084 1014 begin 1085 result := Server(sBuyCityProject, me, cix, nodata^) 1086 end; 1087 1088 function TCustomAI.City_SellImprovement(cix, iix: integer): integer; 1089 begin 1090 result := Server(sSellCityImprovement, me, cix, iix) 1091 end; 1092 1093 function TCustomAI.City_RebuildImprovement(cix, iix: integer): integer; 1094 begin 1095 result := Server(sRebuildCityImprovement, me, cix, iix) 1096 end; 1097 1098 function TCustomAI.City_SetTiles(cix, NewTiles: integer): integer; 1099 begin 1100 result := Server(sSetCityTiles, me, cix, NewTiles) 1101 end; 1102 1103 procedure TCustomAI.City_OptimizeTiles(cix: integer; ResourceWeights: integer); 1104 var 1105 Advice: TCityTileAdviceData; 1106 begin 1107 Advice.ResourceWeights := ResourceWeights; 1108 Server(sGetCityTileAdvice, me, cix, Advice); 1109 City_SetTiles(cix, Advice.Tiles); 1110 end; 1015 result:=Server(sBuyCityProject,me,cix,nodata^) 1016 end; 1017 1018 function TCustomAI.City_SellImprovement(cix,iix: integer): integer; 1019 begin 1020 result:=Server(sSellCityImprovement,me,cix,iix) 1021 end; 1022 1023 function TCustomAI.City_RebuildImprovement(cix,iix: integer): integer; 1024 begin 1025 result:=Server(sRebuildCityImprovement,me,cix,iix) 1026 end; 1027 1028 function TCustomAI.City_SetTiles(cix,NewTiles: integer): integer; 1029 begin 1030 result:=Server(sSetCityTiles,me,cix,NewTiles) 1031 end; 1032 1033 procedure TCustomAI.City_OptimizeTiles(cix: integer; ResourceWeights: cardinal); 1034 var 1035 Advice: TCityTileAdviceData; 1036 begin 1037 Advice.ResourceWeights:=ResourceWeights; 1038 Server(sGetCityTileAdvice, me, cix, Advice); 1039 City_SetTiles(cix, Advice.Tiles); 1040 end; 1041 1111 1042 1112 1043 // negotiation 1113 1044 function TCustomAI.Nego_CheckMyAction: integer; 1114 1045 begin 1115 assert(Opponent >= 0); // only allowed in negotiation mode 1116 assert((MyAction = scDipNotice) or (MyAction = scDipAccept) or 1117 (MyAction = scDipCancelTreaty) or (MyAction = scDipOffer) or 1118 (MyAction = scDipBreak)); 1119 if MyAction = scDipOffer then 1120 result := Server(MyAction - sExecute, me, 0, MyOffer) 1121 else 1122 result := Server(MyAction - sExecute, me, 0, nodata^); 1123 end; 1046 assert(Opponent>=0); // only allowed in negotiation mode 1047 assert((MyAction=scDipNotice) or (MyAction=scDipAccept) 1048 or (MyAction=scDipCancelTreaty) or (MyAction=scDipOffer) 1049 or (MyAction=scDipBreak)); 1050 if MyAction=scDipOffer then result:=Server(MyAction-sExecute, me, 0, MyOffer) 1051 else result:=Server(MyAction-sExecute, me, 0, nodata^); 1052 end; 1053 1124 1054 1125 1055 initialization 1126 1127 nodata := pointer(0); 1128 RWDataSize := 0; 1056 nodata:=pointer(0); 1057 RWDataSize:=0; 1129 1058 1130 1059 end. 1060
Note:
See TracChangeset
for help on using the changeset viewer.
