Changeset 160 for trunk/AI/StdAI/CustomAI.pas
- Timestamp:
- Mar 6, 2019, 8:10:23 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/AI/StdAI/CustomAI.pas
r124 r160 5 5 6 6 uses 7 {$IFDEF DEBUG}SysUtils, 7 {$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, 156 procedure V8_to_ab(V8: integer; var a, 157 procedure ab_to_V21(a, 158 procedure V21_to_ab(V21: integer; var a, 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 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 183 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 229 230 215 neg edx 216 cmp eax,edx 217 jnl @ok 231 218 sub eax,edx 232 219 sub eax,edx 233 220 234 221 // return results 235 222 @ok: 236 237 238 239 240 241 242 243 244 245 223 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 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 292 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 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 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.