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

Legend:

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

    r210 r303  
    99
    1010type
    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;
    115   end;
    116 
    117 
    118 var
    119 Server: TServerCall;
    120 G: TNewGameData;
    121 RWDataSize, MapSize: integer;
    122 decompose24: cardinal;
    123 nodata: pointer;
     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;
     74      var RemainingMovement: integer): boolean;
     75    function Unit_AttackForecast(uix, ToLoc, AttackMovement: integer;
     76      var RemainingHealth: integer): boolean;
     77    function Unit_DefenseForecast(euix, ToLoc: integer;
     78      var RemainingHealth: integer): boolean;
     79    function Unit_Disband(uix: integer): integer;
     80    function Unit_StartJob(uix, NewJob: integer): integer;
     81    function Unit_SetHomeHere(uix: integer): integer;
     82    function Unit_Load(uix: integer): integer;
     83    function Unit_Unload(uix: integer): integer;
     84    function Unit_SelectTransport(uix: integer): integer;
     85    function Unit_AddToCity(uix: integer): integer;
     86
     87    // city functions
     88    procedure City_FindMyCity(Loc: integer; var cix: integer);
     89    procedure City_FindEnemyCity(Loc: integer; var ecix: integer);
     90    function City_HasProject(cix: integer): boolean;
     91    function City_CurrentImprovementProject(cix: integer): integer;
     92    function City_CurrentUnitProject(cix: integer): integer;
     93    function City_GetTileInfo(cix, TileLoc: integer; var TileInfo: TTileInfo): integer;
     94    function City_GetReport(cix: integer; var Report: TCityReport): integer;
     95    function City_GetHypoReport(cix, HypoTiles, HypoTax, HypoLux: integer;
     96      var Report: TCityReport): integer;
     97    function City_GetReportNew(cix: integer; var Report: TCityReportNew): integer;
     98    function City_GetHypoReportNew(cix, HypoTiles, HypoTaxRate, HypoLuxuryRate: integer;
     99      var Report: TCityReportNew): integer;
     100    function City_GetAreaInfo(cix: integer; var AreaInfo: TCityAreaInfo): integer;
     101    function City_StartUnitProduction(cix, mix: integer): integer;
     102    function City_StartEmigration(cix, mix: integer;
     103      AllowDisbandCity, AsConscripts: boolean): integer;
     104    function City_StartImprovement(cix, iix: integer): integer;
     105    function City_Improvable(cix, iix: integer): boolean;
     106    function City_StopProduction(cix: integer): integer;
     107    function City_BuyProject(cix: integer): integer;
     108    function City_SellImprovement(cix, iix: integer): integer;
     109    function City_RebuildImprovement(cix, iix: integer): integer;
     110    function City_SetTiles(cix, NewTiles: integer): integer;
     111    procedure City_OptimizeTiles(cix: integer; ResourceWeights: cardinal = rwMaxGrowth);
     112
     113    // negotiation
     114    function Nego_CheckMyAction: integer;
     115
     116  private
     117    HaveTurned: boolean;
     118    UnwantedNego: set of 0..nPl - 1;
     119    Contacted: set of 0..nPl - 1;
     120    procedure StealAdvance;
     121  end;
     122
     123
     124var
     125  Server: TServerCall;
     126  G: TNewGameData;
     127  RWDataSize, MapSize: integer;
     128  decompose24: cardinal;
     129  nodata: pointer;
    124130
    125131const
    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
     132  CityOwnTile = 13; // = ab_to_V21(0,0)
     133
     134  // additional return codes
     135  rLocationReached = $00010000;
     136  // Unit_Move: move was not interrupted, location reached
     137  rMoreTurns = $00020000;
     138// Unit_Move: move was not interrupted, location not reached yet
    131139
    132140type
    133 TVicinity8Loc=array[0..7] of integer;
    134 TVicinity21Loc=array[0..27] of integer;
     141  TVicinity8Loc = array[0..7] of integer;
     142  TVicinity21Loc = array[0..27] of integer;
    135143
    136144
    137145procedure Init(NewGameData: TNewGameData);
    138146
    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);
     147procedure ab_to_Loc(Loc0, a, b: integer; var Loc: integer);
     148procedure Loc_to_ab(Loc0, Loc: integer; var a, b: integer);
     149procedure ab_to_V8(a, b: integer; var V8: integer);
     150procedure V8_to_ab(V8: integer; var a, b: integer);
     151procedure ab_to_V21(a, b: integer; var V21: integer);
     152procedure V21_to_ab(V21: integer; var a, b: integer);
    145153procedure V8_to_Loc(Loc0: integer; var VicinityLoc: TVicinity8Loc);
    146154procedure V21_to_Loc(Loc0: integer; var VicinityLoc: TVicinity21Loc);
    147 function Distance(Loc0,Loc1: integer): integer;
     155function Distance(Loc0, Loc1: integer): integer;
    148156
    149157
     
    151159
    152160const
    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);
     161  ab_v8: array[-4..4] of integer = (5, 6, 7, 4, -1, 0, 3, 2, 1);
     162  v8_a: array[0..7] of integer = (1, 1, 0, -1, -1, -1, 0, 1);
     163  v8_b: array[0..7] of integer = (0, 1, 1, 1, 0, -1, -1, -1);
     164
     165
     166procedure ab_to_Loc(Loc0, a, b: integer; var Loc: integer);
    159167{relative location from Loc0}
    160168var
    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);
    170 {$IFDEF FPC} // freepascal
    171 var
    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;
    179 end;
    180 {$ELSE} // delphi
     169  y0: integer;
     170begin
     171  assert((Loc0 >= 0) and (Loc0 < MapSize) and (a - b + G.lx >= 0));
     172  y0 := cardinal(Loc0) * decompose24 shr 24;
     173  Loc := (Loc0 + (a - b + y0 and 1 + G.lx + G.lx) shr 1) mod G.lx + G.lx * (y0 + a + b);
     174  if Loc >= MapSize then
     175    Loc := -$1000;
     176end;
     177
     178procedure Loc_to_ab(Loc0, Loc: integer; var a, b: integer);
     179{$IFDEF FPC}// freepascal
     180var
     181  dx, dy: integer;
     182begin
     183  dx := ((Loc mod G.lx * 2 + Loc div G.lx and 1) - (Loc0 mod G.lx * 2 + Loc0 div
     184    G.lx and 1) + 3 * G.lx) mod (2 * G.lx) - G.lx;
     185  dy := Loc div G.lx - Loc0 div G.lx;
     186  a := (dx + dy) div 2;
     187  b := (dy - dx) div 2;
     188end;
     189
     190{$ELSE}// delphi
    181191register;
    182192asm
     
    234244{$ENDIF}
    235245
    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;
     246procedure ab_to_V8(a, b: integer; var V8: integer);
     247begin
     248  assert((abs(a) <= 1) and (abs(b) <= 1) and ((a <> 0) or (b <> 0)));
     249  V8 := ab_v8[2 * b + b + a];
     250end;
     251
     252procedure V8_to_ab(V8: integer; var a, b: integer);
     253begin
     254  a := v8_a[V8];
     255  b := V8_b[V8];
     256end;
     257
     258procedure ab_to_V21(a, b: integer; var V21: integer);
     259begin
     260  V21 := (a + b + 3) shl 2 + (a - b + 3) shr 1;
     261end;
     262
     263procedure V21_to_ab(V21: integer; var a, b: integer);
     264var
     265  dx, dy: integer;
     266begin
     267  dy := V21 shr 2 - 3;
     268  dx := V21 and 3 shl 1 - 3 + (dy + 3) and 1;
     269  a := (dx + dy) div 2;
     270  b := (dy - dx) div 2;
    260271end;
    261272
    262273procedure V8_to_Loc(Loc0: integer; var VicinityLoc: TVicinity8Loc);
    263274var
    264 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
     275  x0, y0, lx: integer;
     276begin
     277  lx := G.lx;
     278  y0 := cardinal(Loc0) * decompose24 shr 24;
     279  x0 := Loc0 - y0 * lx; // Loc0 mod lx;
     280  VicinityLoc[1] := Loc0 + lx * 2;
     281  VicinityLoc[3] := Loc0 - 1;
     282  VicinityLoc[5] := Loc0 - lx * 2;
     283  VicinityLoc[7] := Loc0 + 1;
     284  Inc(Loc0, y0 and 1);
     285  VicinityLoc[0] := Loc0 + lx;
     286  VicinityLoc[2] := Loc0 + lx - 1;
     287  VicinityLoc[4] := Loc0 - lx - 1;
     288  VicinityLoc[6] := Loc0 - lx;
     289
     290  // world is round!
     291  if x0 < lx - 1 then
    281292  begin
    282   if x0=0 then
     293    if x0 = 0 then
    283294    begin
    284     inc(VicinityLoc[3],lx);
    285     if y0 and 1=0 then
     295      Inc(VicinityLoc[3], lx);
     296      if y0 and 1 = 0 then
    286297      begin
    287       inc(VicinityLoc[2],lx);
    288       inc(VicinityLoc[4],lx);
     298        Inc(VicinityLoc[2], lx);
     299        Inc(VicinityLoc[4], lx);
     300      end;
     301    end;
     302  end
     303  else
     304  begin
     305    Dec(VicinityLoc[7], lx);
     306    if y0 and 1 = 1 then
     307    begin
     308      Dec(VicinityLoc[0], lx);
     309      Dec(VicinityLoc[6], lx);
     310    end;
     311  end;
     312
     313  // check south pole
     314  case G.ly - y0 of
     315    1:
     316    begin
     317      VicinityLoc[0] := -$1000;
     318      VicinityLoc[1] := -$1000;
     319      VicinityLoc[2] := -$1000;
     320    end;
     321    2: VicinityLoc[1] := -$1000;
     322  end;
     323end;
     324
     325procedure V21_to_Loc(Loc0: integer; var VicinityLoc: TVicinity21Loc);
     326var
     327  dx, dy, bit, y0, xComp, yComp, xComp0, xCompSwitch: integer;
     328  dst: ^integer;
     329begin
     330  y0 := cardinal(Loc0) * decompose24 shr 24;
     331  xComp0 := Loc0 - y0 * G.lx - 1; // Loc0 mod G.lx -1
     332  xCompSwitch := xComp0 - 1 + y0 and 1;
     333  if xComp0 < 0 then
     334    Inc(xComp0, G.lx);
     335  if xCompSwitch < 0 then
     336    Inc(xCompSwitch, G.lx);
     337  xCompSwitch := xCompSwitch xor xComp0;
     338  yComp := G.lx * (y0 - 3);
     339  dst := @VicinityLoc;
     340  bit := 1;
     341  for dy := 0 to 6 do
     342    if yComp < MapSize then
     343    begin
     344      xComp0 := xComp0 xor xCompSwitch;
     345      xComp := xComp0;
     346      for dx := 0 to 3 do
     347      begin
     348        if bit and $67F7F76 <> 0 then
     349          dst^ := xComp + yComp
     350        else
     351          dst^ := -1;
     352        Inc(xComp);
     353        if xComp >= G.lx then
     354          Dec(xComp, G.lx);
     355        Inc(dst);
     356        bit := bit shl 1;
     357      end;
     358      Inc(yComp, G.lx);
     359    end
     360    else
     361    begin
     362      for dx := 0 to 3 do
     363      begin
     364        dst^ := -$1000;
     365        Inc(dst);
     366      end;
     367    end;
     368end;
     369
     370function Distance(Loc0, Loc1: integer): integer;
     371var
     372  a, b, dx, dy: integer;
     373begin
     374  Loc_to_ab(Loc0, Loc1, a, b);
     375  dx := abs(a - b);
     376  dy := abs(a + b);
     377  Result := dx + dy + abs(dx - dy) shr 1;
     378end;
     379
     380
     381procedure Init(NewGameData: TNewGameData);
     382{$IFDEF DEBUG}var
     383  Loc: integer;
     384{$ENDIF}
     385begin
     386  G := NewGameData;
     387  MapSize := G.lx * G.ly;
     388  decompose24 := (1 shl 24 - 1) div G.lx + 1;
     389{$IFDEF DEBUG}
     390  for Loc := 0 to MapSize - 1 do
     391    assert(cardinal(Loc) * decompose24 shr 24 = cardinal(Loc div G.lx));
     392{$ENDIF}
     393end;
     394
     395
     396constructor TCustomAI.Create(Nation: integer);
     397begin
     398  inherited Create;
     399  me := Nation;
     400  RO := pointer(G.RO[Nation]);
     401  Map := pointer(RO.Map);
     402  MyUnit := pointer(RO.Un);
     403  MyCity := pointer(RO.City);
     404  MyModel := pointer(RO.Model);
     405  Opponent := -1;
     406end;
     407
     408destructor TCustomAI.Destroy;
     409begin
     410  Server(sSetDebugMap, me, 0, nodata^);
     411end;
     412
     413
     414procedure TCustomAI.Process(Command: integer; var Data);
     415var
     416  Nation, NewResearch, NewGov, Count, ad, cix, iix: integer;
     417  NegoTime: TNegoTime;
     418begin
     419  case Command of
     420    cTurn, cContinue:
     421    begin
     422      if RO.Alive and (1 shl me) = 0 then
     423      begin // I'm dead, huhu
     424        Server(sTurn, me, 0, nodata^);
     425        exit;
     426      end;
     427      if Command = cTurn then
     428      begin
     429        fillchar(cixStateImp, sizeof(cixStateImp), $FF);
     430        for cix := 0 to RO.nCity - 1 do
     431          if MyCity[cix].Loc >= 0 then
     432            for iix := imPalace to imSpacePort do
     433              if MyCity[cix].Built[iix] > 0 then
     434                cixStateImp[iix] := cix;
     435        if RO.Happened and phChangeGov <> 0 then
     436        begin
     437          NewGov := ChooseGovernment;
     438          if NewGov > gAnarchy then
     439            Server(sSetGovernment, me, NewGov, nodata^);
     440        end;
     441        HaveTurned := False;
     442        Contacted := [];
     443      end;
     444      if (Command = cContinue) and (MyAction = scContact) then
     445      begin
     446        if OnNegoRejected_CancelTreaty then
     447          if RO.Treaty[Opponent] >= trPeace then
     448            if Server(sCancelTreaty, me, 0, nodata^) < rExecuted then
     449              assert(False);
    289450      end
    290     end
    291   end
    292 else
    293   begin
    294   dec(VicinityLoc[7],lx);
    295   if y0 and 1=1 then
     451      else
     452        UnwantedNego := [];
     453      Opponent := -1;
     454      repeat
     455        if HaveTurned then
     456          NegoTime := EndOfTurn
     457        else
     458          NegoTime := BeginOfTurn;
     459        if RO.Government <> gAnarchy then
     460          for Nation := 0 to nPl - 1 do
     461            if (Nation <> me) and (1 shl Nation and RO.Alive <> 0) and
     462              (RO.Treaty[Nation] >= trNone) and not (Nation in Contacted) and not
     463              (Nation in UnwantedNego) and
     464              (Server(scContact - sExecute + Nation shl 4, me, 0, nodata^) >= rExecuted) then
     465              if WantNegotiation(Nation, NegoTime) then
     466              begin
     467                if Server(scContact + Nation shl 4, me, 0, nodata^) >= rExecuted then
     468                begin
     469                  include(Contacted, Nation);
     470                  Opponent := Nation;
     471                  MyAction := scContact;
     472                  exit;
     473                end;
     474              end
     475              else
     476                include(UnwantedNego, Nation);
     477        if NegoTime = BeginOfTurn then
     478        begin
     479          DoTurn;
     480          HaveTurned := True;
     481          Contacted := [];
     482          UnwantedNego := [];
     483        end
     484        else
     485          break;
     486      until False;
     487      if RO.Happened and phTech <> 0 then
     488      begin
     489        NewResearch := ChooseResearchAdvance;
     490        if NewResearch < 0 then
     491        begin // choose random research
     492          Count := 0;
     493          for ad := 0 to nAdv - 1 do
     494            if AdvanceResearchable(ad) then
     495            begin
     496              Inc(Count);
     497              if random(Count) = 0 then
     498                NewResearch := ad;
     499            end;
     500        end;
     501        Server(sSetResearch, me, NewResearch, nodata^);
     502      end;
     503      if Server(sTurn, me, 0, nodata^) < rExecuted then
     504        assert(False);
     505    end;
     506    scContact:
     507      if WantNegotiation(integer(Data), EnemyCalled) then
     508      begin
     509        if Server(scDipStart, me, 0, nodata^) < rExecuted then
     510          assert(False);
     511        Opponent := integer(Data);
     512        MyAction := scDipStart;
     513      end
     514      else
     515      begin
     516        if Server(scReject, me, 0, nodata^) < rExecuted then
     517          assert(False);
     518      end;
     519    scDipStart, scDipNotice, scDipAccept, scDipCancelTreaty, scDipOffer, scDipBreak:
    296520    begin
    297     dec(VicinityLoc[0],lx);
    298     dec(VicinityLoc[6],lx);
    299     end
    300   end;
    301 
    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;
     521      OppoAction := Command;
     522      if Command = scDipOffer then
     523        OppoOffer := TOffer(Data);
     524      if Command = scDipStart then
     525        MyLastAction := scContact
     526      else
     527      begin
     528        MyLastAction := MyAction;
     529        MyLastOffer := MyOffer;
     530      end;
     531      if (OppoAction = scDipCancelTreaty) or (OppoAction = scDipBreak) then
     532        MyAction := scDipNotice
     533      else
     534      begin
     535        MyAction := scDipOffer;
     536        MyOffer.nDeliver := 0;
     537        MyOffer.nCost := 0;
     538      end;
     539      DoNegotiation;
     540      assert((MyAction = scDipNotice) or (MyAction = scDipAccept) or
     541        (MyAction = scDipCancelTreaty) or (MyAction = scDipOffer) or (MyAction = scDipBreak));
     542      if MyAction = scDipOffer then
     543        Server(MyAction, me, 0, MyOffer)
     544      else
     545        Server(MyAction, me, 0, nodata^);
    309546    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
    334       begin
    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;
    341       end;
    342     inc(yComp,G.lx);
    343     end
    344   else
    345     begin
    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
    404       begin
    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:=[];
    418       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
    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:
    485     begin
    486     OppoAction:=Command;
    487     if Command=scDipOffer then OppoOffer:=TOffer(Data);
    488     if Command=scDipStart then
    489       MyLastAction:=scContact
    490     else
    491       begin
    492       MyLastAction:=MyAction;
    493       MyLastOffer:=MyOffer;
    494       end;
    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;
     547    cShowEndContact:
     548      Opponent := -1;
    507549  end;
    508550end;
     
    525567end;
    526568
    527 procedure TCustomAI.OnBeforeEnemyAttack(UnitInfo: TUnitInfo; ToLoc, EndHealth,
    528   EndHealthDef: integer);
     569procedure TCustomAI.OnBeforeEnemyAttack(UnitInfo: TUnitInfo;
     570  ToLoc, EndHealth, EndHealthDef: integer);
    529571begin
    530572end;
     
    544586function TCustomAI.ChooseResearchAdvance: integer;
    545587begin
    546 result:=-1
     588  Result := -1;
    547589end;
    548590
    549591function TCustomAI.ChooseStealAdvance: integer;
    550592begin
    551 result:=-1
     593  Result := -1;
    552594end;
    553595
    554596function TCustomAI.ChooseGovernment: integer;
    555597begin
    556 result:=gDespotism
     598  Result := gDespotism;
    557599end;
    558600
    559601function TCustomAI.WantNegotiation(Nation: integer; NegoTime: TNegoTime): boolean;
    560602begin
    561 result:=false;
     603  Result := False;
    562604end;
    563605
    564606function TCustomAI.OnNegoRejected_CancelTreaty: boolean;
    565607begin
    566 result:=false;
    567 end;
     608  Result := False;
     609end;
     610
    568611{$HINTS ON}
    569612
    570613procedure TCustomAI.StealAdvance;
    571614var
    572 Steal, ad, count: integer;
    573 begin
    574 Steal:=ChooseStealAdvance;
    575 if Steal<0 then
     615  Steal, ad, Count: integer;
     616begin
     617  Steal := ChooseStealAdvance;
     618  if Steal < 0 then
    576619  begin // choose random advance
    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
    580   end;
    581 if Steal>=0 then Server(sStealTech,me,Steal,nodata^);
    582 RO.Happened:=RO.Happened and not phStealTech
     620    Count := 0;
     621    for ad := 0 to nAdv - 1 do
     622      if AdvanceStealable(ad) then
     623      begin
     624        Inc(Count);
     625        if random(Count) = 0 then
     626          Steal := ad;
     627      end;
     628  end;
     629  if Steal >= 0 then
     630    Server(sStealTech, me, Steal, nodata^);
     631  RO.Happened := RO.Happened and not phStealTech;
    583632end;
    584633
    585634function TCustomAI.IsResearched(Advance: integer): boolean;
    586635begin
    587 result:= (Advance=preNone)
    588   or (Advance<>preNA) and (RO.Tech[Advance]>=tsApplicable)
     636  Result := (Advance = preNone) or (Advance <> preNA) and (RO.Tech[Advance] >= tsApplicable);
    589637end;
    590638
    591639function TCustomAI.ResearchCost: integer;
    592640begin
    593 Server(sGetTechCost,me,0,result)
     641  Server(sGetTechCost, me, 0, Result);
    594642end;
    595643
    596644function TCustomAI.ChangeAttitude(Nation, Attitude: integer): integer;
    597645begin
    598 result:=Server(sSetAttitude+Nation shl 4,me,Attitude,nodata^)
     646  Result := Server(sSetAttitude + Nation shl 4, me, Attitude, nodata^);
    599647end;
    600648
    601649function TCustomAI.Revolution: integer;
    602650begin
    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^)
     651  Result := Server(sRevolution, me, 0, nodata^);
     652end;
     653
     654function TCustomAI.ChangeRates(Tax, Lux: integer): integer;
     655begin
     656  Result := Server(sSetRates, me, Tax div 10 and $f + Lux div 10 and $f shl 4, nodata^);
    609657end;
    610658
    611659function TCustomAI.PrepareNewModel(Domain: integer): integer;
    612660begin
    613 result:=Server(sCreateDevModel,me,Domain,nodata^);
     661  Result := Server(sCreateDevModel, me, Domain, nodata^);
    614662end;
    615663
    616664function TCustomAI.SetNewModelFeature(F, Count: integer): integer;
    617665begin
    618 result:=Server(sSetDevModelCap+Count shl 4,me,F,nodata^)
     666  Result := Server(sSetDevModelCap + Count shl 4, me, F, nodata^);
    619667end;
    620668
    621669function TCustomAI.AdvanceResearchable(Advance: integer): boolean;
    622670begin
    623 result:= Server(sSetResearch-sExecute,me,Advance,nodata^)>=rExecuted;
     671  Result := Server(sSetResearch - sExecute, me, Advance, nodata^) >= rExecuted;
    624672end;
    625673
    626674function TCustomAI.AdvanceStealable(Advance: integer): boolean;
    627675begin
    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;
     676  Result := Server(sStealTech - sExecute, me, Advance, nodata^) >= rExecuted;
     677end;
     678
     679function TCustomAI.GetJobProgress(Loc: integer;
     680  var JobProgress: TJobProgressData): boolean;
     681begin
     682  Result := Server(sGetJobProgress, me, Loc, JobProgress) >= rExecuted;
    634683end;
    635684
    636685function TCustomAI.DebugMessage(Level: integer; Text: string): boolean;
    637686begin
    638 Text:=copy('P'+char(48+me)+' '+Text,1,254);
    639 Server(sMessage,me,Level,pchar(Text)^);
    640 
    641 result:=true;
     687  Text := copy('P' + char(48 + me) + ' ' + Text, 1, 254);
     688  Server(sMessage, me, Level, PChar(Text)^);
     689
     690  Result := True;
    642691  // always returns true so that it can be used like
    643692  // "assert(DebugMessage(...));" -> not compiled in release build
     
    646695function TCustomAI.SetDebugMap(var DebugMap): boolean;
    647696begin
    648 Server(sSetDebugMap, me, 0, DebugMap);
    649 
    650 result:=true;
     697  Server(sSetDebugMap, me, 0, DebugMap);
     698
     699  Result := True;
    651700  // always returns true so that it can be used like
    652701  // "assert(SetDebugMap(...));" -> not compiled in release build
     
    655704procedure TCustomAI.Unit_FindMyDefender(Loc: integer; var uix: integer);
    656705begin
    657 if Server(sGetDefender,me,Loc,uix)<rExecuted then uix:=-1
     706  if Server(sGetDefender, me, Loc, uix) < rExecuted then
     707    uix := -1;
    658708end;
    659709
    660710procedure TCustomAI.Unit_FindEnemyDefender(Loc: integer; var euix: integer);
    661711begin
    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
     712  euix := RO.nEnemyUn - 1;
     713  while (euix >= 0) and (RO.EnemyUn[euix].Loc <> Loc) do
     714    Dec(euix);
     715end;
     716
     717function TCustomAI.Unit_Move(uix, ToLoc: integer): integer;
     718var
     719  Step: integer;
     720  DestinationReached: boolean;
     721  Advice: TMoveAdviceData;
     722begin
     723  assert((uix >= 0) and (uix < RO.nUn) and (MyUnit[uix].Loc >= 0)); // is a unit
    674724{Loc_to_ab(MyUnit[uix].Loc,ToLoc,a,b);
    675725assert((a<>0) or (b<>0));
     
    686736else}
    687737  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
     738    Advice.ToLoc := ToLoc;
     739    Advice.MoreTurns := 9999;
     740    Advice.MaxHostile_MovementLeft := 100;
     741    Result := Server(sGetMoveAdvice, me, uix, Advice);
     742  end;
     743  if Result = eOk then
    694744  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;
     745    DestinationReached := False;
     746    Step := 0;
     747    repeat
     748      if Result and (rExecuted or rUnitRemoved) = rExecuted then
     749        // check if destination reached
     750        if (ToLoc >= 0) and (Advice.MoreTurns = 0) and (Step = Advice.nStep - 1) and
     751          ((Map[ToLoc] and (fUnit or fOwned) = fUnit) // attack
     752          or (Map[ToLoc] and (fCity or fOwned) = fCity) and
     753          ((MyModel[MyUnit[uix].mix].Domain <> dGround) // bombardment
     754          or (MyModel[MyUnit[uix].mix].Flags and mdCivil <> 0))) then // can't capture
     755        begin
     756          DestinationReached := True;
     757          break;
     758        end // stop next to destination
     759        else if Step = Advice.nStep then
     760          DestinationReached := True; // normal move -- stop at destination
     761
     762      if (Step = Advice.nStep) or (Result <> eOK) and (Result <> eLoaded) then
     763        break;
     764
     765      Result := Server(sMoveUnit + (Advice.dx[Step] and 7) shl 4 +
     766        (Advice.dy[Step] and 7) shl 7, me, uix, nodata^);
     767      Inc(Step);
     768      if RO.Happened and phStealTech <> 0 then
     769        StealAdvance;
     770    until False;
     771    if DestinationReached then
     772      if Advice.nStep = 25 then
     773        Result := Unit_Move(uix, ToLoc) // Shinkansen
     774      else if Advice.MoreTurns = 0 then
     775        Result := Result or rLocationReached
     776      else
     777        Result := Result or rMoreTurns;
     778  end;
     779end;
     780
     781function TCustomAI.Unit_Step(uix, ToLoc: integer): integer;
     782var
     783  a, b: integer;
     784begin
     785  Loc_to_ab(MyUnit[uix].Loc, ToLoc, a, b);
     786  assert(((a <> 0) or (b <> 0)) and (a >= -1) and (a <= 1) and (b >= -1) and (b <= 1));
     787  Result := Server(sMoveUnit + ((a - b) and 7) shl 4 + ((a + b) and 7) shl 7, me, uix, nodata^);
     788  if RO.Happened and phStealTech <> 0 then
     789    StealAdvance;
     790end;
     791
     792function TCustomAI.Unit_Attack(uix, ToLoc: integer): integer;
     793var
     794  a, b: integer;
     795begin
     796  assert((uix >= 0) and (uix < RO.nUn) and (MyUnit[uix].Loc >= 0) // is a unit
     797    and ((Map[ToLoc] and (fUnit or fOwned) = fUnit) // is an attack
     798    or (Map[ToLoc] and (fCity or fOwned) = fCity) and
     799    (MyModel[MyUnit[uix].mix].Domain <> dGround))); // is a bombardment
     800  Loc_to_ab(MyUnit[uix].Loc, ToLoc, a, b);
     801  assert(((a <> 0) or (b <> 0)) and (a >= -1) and (a <= 1) and (b >= -1) and (b <= 1));
     802  // attack to adjacent tile
     803  Result := Server(sMoveUnit + (a - b) and 7 shl 4 + (a + b) and 7 shl 7, me, uix, nodata^);
     804end;
     805
     806function TCustomAI.Unit_DoMission(uix, MissionType, ToLoc: integer): integer;
     807var
     808  a, b: integer;
     809begin
     810  Result := Server(sSetSpyMission + MissionType shl 4, me, 0, nodata^);
     811  if Result >= rExecuted then
     812  begin
     813    assert((uix >= 0) and (uix < RO.nUn) and (MyUnit[uix].Loc >= 0) // is a unit
     814      and (MyModel[MyUnit[uix].mix].Kind = mkDiplomat)); // is a commando
     815    Loc_to_ab(MyUnit[uix].Loc, ToLoc, a, b);
     816    assert(((a <> 0) or (b <> 0)) and (a >= -1) and (a <= 1) and (b >= -1) and (b <= 1));
     817    // city must be adjacent
     818    Result := Server(sMoveUnit - sExecute + (a - b) and 7 shl 4 + (a + b) and 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, me, uix, nodata^)
     821    else if (Result <> eNoTime_Move) and (Result <> eTreaty) and (Result <> eNoTurn) then
     822      Result := eInvalid; // not a special commando mission!
     823  end;
     824end;
     825
     826function TCustomAI.Unit_MoveForecast(uix, ToLoc: integer;
     827  var RemainingMovement: integer): boolean;
     828var
     829  Advice: TMoveAdviceData;
     830begin
     831  assert((uix >= 0) and (uix < RO.nUn) and (MyUnit[uix].Loc >= 0)); // is a unit
     832  Advice.ToLoc := ToLoc;
     833  Advice.MoreTurns := 0;
     834  Advice.MaxHostile_MovementLeft := 100;
     835  if Server(sGetMoveAdvice, me, uix, Advice) = eOk then
     836  begin
     837    RemainingMovement := Advice.MaxHostile_MovementLeft;
     838    Result := True;
    722839  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
     840  else
    754841  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
     842    RemainingMovement := -1;
     843    Result := False;
     844  end;
     845end;
     846
     847// negative RemainingHealth is remaining helth of defender if lost
     848function TCustomAI.Unit_AttackForecast(uix, ToLoc, AttackMovement: integer;
     849  var RemainingHealth: integer): boolean;
     850var
     851  BattleForecast: TBattleForecast;
     852begin
     853  assert((uix >= 0) and (uix < RO.nUn) and (MyUnit[uix].Loc >= 0) // is a unit
     854    and (Map[ToLoc] and (fUnit or fOwned) = fUnit)); // is an attack
     855  RemainingHealth := -$100;
     856  Result := False;
     857  if AttackMovement >= 0 then
     858    with MyUnit[uix] do
     859    begin
     860      BattleForecast.pAtt := me;
     861      BattleForecast.mixAtt := mix;
     862      BattleForecast.HealthAtt := Health;
     863      BattleForecast.ExpAtt := Exp;
     864      BattleForecast.FlagsAtt := Flags;
     865      BattleForecast.Movement := AttackMovement;
     866      if Server(sGetBattleForecast, me, ToLoc, BattleForecast) >= rExecuted then
     867      begin
     868        if BattleForecast.EndHealthAtt > 0 then
     869          RemainingHealth := BattleForecast.EndHealthAtt
     870        else
     871          RemainingHealth := -BattleForecast.EndHealthDef;
     872        Result := True;
     873      end;
     874    end;
     875end;
     876
     877function TCustomAI.Unit_DefenseForecast(euix, ToLoc: integer;
     878  var RemainingHealth: integer): boolean;
     879var
     880  BattleForecast: TBattleForecast;
     881begin
     882  assert((euix >= 0) and (euix < RO.nEnemyUn) and (RO.EnemyUn[euix].Loc >= 0) // is an enemy unit
     883    and (Map[ToLoc] and (fUnit or fOwned) = (fUnit or fOwned))); // is an attack
     884  RemainingHealth := $100;
     885  Result := False;
     886  with RO.EnemyUn[euix] do
    777887  begin
    778   RemainingMovement:=Advice.MaxHostile_MovementLeft;
    779   result:=true
    780   end
    781 else
     888    BattleForecast.pAtt := Owner;
     889    BattleForecast.mixAtt := mix;
     890    BattleForecast.HealthAtt := Health;
     891    BattleForecast.ExpAtt := Exp;
     892    BattleForecast.FlagsAtt := Flags;
     893    BattleForecast.Movement := 100;
     894    if Server(sGetBattleForecast, me, ToLoc, BattleForecast) >= rExecuted then
     895    begin
     896      if BattleForecast.EndHealthDef > 0 then
     897        RemainingHealth := BattleForecast.EndHealthDef
     898      else
     899        RemainingHealth := -BattleForecast.EndHealthAtt;
     900      Result := True;
     901    end;
     902  end;
     903end;
     904
     905function TCustomAI.Unit_Disband(uix: integer): integer;
     906begin
     907  Result := Server(sRemoveUnit, me, uix, nodata^);
     908end;
     909
     910function TCustomAI.Unit_StartJob(uix, NewJob: integer): integer;
     911begin
     912  Result := Server(sStartJob + NewJob shl 4, me, uix, nodata^);
     913end;
     914
     915function TCustomAI.Unit_SetHomeHere(uix: integer): integer;
     916begin
     917  Result := Server(sSetUnitHome, me, uix, nodata^);
     918end;
     919
     920function TCustomAI.Unit_Load(uix: integer): integer;
     921begin
     922  Result := Server(sLoadUnit, me, uix, nodata^);
     923end;
     924
     925function TCustomAI.Unit_Unload(uix: integer): integer;
     926begin
     927  Result := Server(sUnloadUnit, me, uix, nodata^);
     928end;
     929
     930function TCustomAI.Unit_AddToCity(uix: integer): integer;
     931begin
     932  Result := Server(sAddToCity, me, uix, nodata^);
     933end;
     934
     935function TCustomAI.Unit_SelectTransport(uix: integer): integer;
     936begin
     937  Result := Server(sSelectTransport, me, uix, nodata^);
     938end;
     939
     940
     941procedure TCustomAI.City_FindMyCity(Loc: integer; var cix: integer);
     942begin
     943  if Map[Loc] and (fCity or fOwned) <> fCity or fOwned then
     944    cix := -1
     945  else
    782946  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
     947    cix := RO.nCity - 1;
     948    while (cix >= 0) and (MyCity[cix].Loc <> Loc) do
     949      Dec(cix);
     950  end;
     951end;
     952
     953procedure TCustomAI.City_FindEnemyCity(Loc: integer; var ecix: integer);
     954begin
     955  if Map[Loc] and (fCity or fOwned) <> fCity then
     956    ecix := -1
     957  else
    799958  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
    812     end
    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
     959    ecix := RO.nEnemyCity - 1;
     960    while (ecix >= 0) and (RO.EnemyCity[ecix].Loc <> Loc) do
     961      Dec(ecix);
     962  end;
     963end;
     964
     965function TCustomAI.City_HasProject(cix: integer): boolean;
     966begin
     967  Result := MyCity[cix].Project and (cpImp + cpIndex) <> cpImp + imTrGoods;
     968end;
     969
     970function TCustomAI.City_CurrentImprovementProject(cix: integer): integer;
     971begin
     972  if MyCity[cix].Project and cpImp = 0 then
     973    Result := -1
     974  else
    826975  begin
    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
    884   begin
    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
    896   begin
    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
    912   begin
    913   result:=MyCity[cix].Project and cpIndex;
    914   if result=imTrGoods then result:=-1
    915   end
     976    Result := MyCity[cix].Project and cpIndex;
     977    if Result = imTrGoods then
     978      Result := -1;
     979  end;
    916980end;
    917981
    918982function TCustomAI.City_CurrentUnitProject(cix: integer): integer;
    919983begin
    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)
     984  if MyCity[cix].Project and cpImp <> 0 then
     985    Result := -1
     986  else
     987    Result := MyCity[cix].Project and cpIndex;
     988end;
     989
     990function TCustomAI.City_GetTileInfo(cix, TileLoc: integer;
     991  var TileInfo: TTileInfo): integer;
     992begin
     993  TileInfo.ExplCity := cix;
     994  Result := Server(sGetHypoCityTileInfo, me, TileLoc, TileInfo);
    928995end;
    929996
    930997function TCustomAI.City_GetReport(cix: integer; var Report: TCityReport): integer;
    931998begin
    932 Report.HypoTiles:=-1;
    933 Report.HypoTax:=-1;
    934 Report.HypoLux:=-1;
    935 result:=Server(sGetCityReport,me,cix,Report)
     999  Report.HypoTiles := -1;
     1000  Report.HypoTax := -1;
     1001  Report.HypoLux := -1;
     1002  Result := Server(sGetCityReport, me, cix, Report);
    9361003end;
    9371004
     
    9391006  var Report: TCityReport): integer;
    9401007begin
    941 Report.HypoTiles:=HypoTiles;
    942 Report.HypoTax:=HypoTax;
    943 Report.HypoLux:=HypoLux;
    944 result:=Server(sGetCityReport,me,cix,Report)
     1008  Report.HypoTiles := HypoTiles;
     1009  Report.HypoTax := HypoTax;
     1010  Report.HypoLux := HypoLux;
     1011  Result := Server(sGetCityReport, me, cix, Report);
    9451012end;
    9461013
    9471014function TCustomAI.City_GetReportNew(cix: integer; var Report: TCityReportNew): integer;
    9481015begin
    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;
    956   var Report: TCityReportNew): integer;
    957 begin
    958 Report.HypoTiles:=HypoTiles;
    959 Report.HypoTaxRate:=HypoTaxRate;
    960 Report.HypoLuxuryRate:=HypoLuxuryRate;
    961 result:=Server(sGetCityReportNew,me,cix,Report)
     1016  Report.HypoTiles := -1;
     1017  Report.HypoTaxRate := -1;
     1018  Report.HypoLuxuryRate := -1;
     1019  Result := Server(sGetCityReportNew, me, cix, Report);
     1020end;
     1021
     1022function TCustomAI.City_GetHypoReportNew(cix, HypoTiles, HypoTaxRate,
     1023  HypoLuxuryRate: integer; var Report: TCityReportNew): integer;
     1024begin
     1025  Report.HypoTiles := HypoTiles;
     1026  Report.HypoTaxRate := HypoTaxRate;
     1027  Report.HypoLuxuryRate := HypoLuxuryRate;
     1028  Result := Server(sGetCityReportNew, me, cix, Report);
    9621029end;
    9631030
    9641031function TCustomAI.City_GetAreaInfo(cix: integer; var AreaInfo: TCityAreaInfo): integer;
    9651032begin
    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;
     1033  Result := Server(sGetCityAreaInfo, me, cix, AreaInfo);
     1034end;
     1035
     1036function TCustomAI.City_StartUnitProduction(cix, mix: integer): integer;
     1037begin
     1038  if (MyCity[cix].Project and (cpImp + cpIndex) <> mix) then
     1039    // not already producing that
     1040    Result := Server(sSetCityProject, me, cix, mix);
     1041end;
     1042
     1043function TCustomAI.City_StartEmigration(cix, mix: integer;
    9771044  AllowDisbandCity, AsConscripts: boolean): integer;
    9781045var
    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;
     1046  NewProject: integer;
     1047begin
     1048  NewProject := mix;
     1049  if AllowDisbandCity then
     1050    NewProject := NewProject or cpDisbandCity;
     1051  if AsConscripts then
     1052    NewProject := NewProject or cpConscripts;
     1053  Result := Server(sSetCityProject, me, cix, NewProject);
     1054end;
     1055
     1056function TCustomAI.City_StartImprovement(cix, iix: integer): integer;
     1057var
     1058  NewProject: integer;
     1059begin
     1060  NewProject := iix + cpImp;
     1061  if (MyCity[cix].Project and (cpImp + cpIndex) <> NewProject) then
     1062    // not already producing that
     1063    Result := Server(sSetCityProject, me, cix, NewProject);
     1064end;
     1065
     1066function TCustomAI.City_Improvable(cix, iix: integer): boolean;
     1067var
     1068  NewProject: integer;
     1069begin
     1070  NewProject := iix + cpImp;
     1071  Result := Server(sSetCityProject - sExecute, me, cix, NewProject) >= rExecuted;
    10031072end;
    10041073
    10051074function TCustomAI.City_StopProduction(cix: integer): integer;
    10061075var
    1007 NewProject: integer;
    1008 begin
    1009 NewProject:=imTrGoods+cpImp;
    1010 result:=Server(sSetCityProject,me,cix,NewProject)
     1076  NewProject: integer;
     1077begin
     1078  NewProject := imTrGoods + cpImp;
     1079  Result := Server(sSetCityProject, me, cix, NewProject);
    10111080end;
    10121081
    10131082function TCustomAI.City_BuyProject(cix: integer): integer;
    10141083begin
    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)
     1084  Result := Server(sBuyCityProject, me, cix, nodata^);
     1085end;
     1086
     1087function TCustomAI.City_SellImprovement(cix, iix: integer): integer;
     1088begin
     1089  Result := Server(sSellCityImprovement, me, cix, iix);
     1090end;
     1091
     1092function TCustomAI.City_RebuildImprovement(cix, iix: integer): integer;
     1093begin
     1094  Result := Server(sRebuildCityImprovement, me, cix, iix);
     1095end;
     1096
     1097function TCustomAI.City_SetTiles(cix, NewTiles: integer): integer;
     1098begin
     1099  Result := Server(sSetCityTiles, me, cix, NewTiles);
    10311100end;
    10321101
    10331102procedure TCustomAI.City_OptimizeTiles(cix: integer; ResourceWeights: cardinal);
    10341103var
    1035 Advice: TCityTileAdviceData;
    1036 begin
    1037 Advice.ResourceWeights:=ResourceWeights;
    1038 Server(sGetCityTileAdvice, me, cix, Advice);
    1039 City_SetTiles(cix, Advice.Tiles);
     1104  Advice: TCityTileAdviceData;
     1105begin
     1106  Advice.ResourceWeights := ResourceWeights;
     1107  Server(sGetCityTileAdvice, me, cix, Advice);
     1108  City_SetTiles(cix, Advice.Tiles);
    10401109end;
    10411110
     
    10441113function TCustomAI.Nego_CheckMyAction: integer;
    10451114begin
    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^);
     1115  assert(Opponent >= 0); // only allowed in negotiation mode
     1116  assert((MyAction = scDipNotice) or (MyAction = scDipAccept) or
     1117    (MyAction = scDipCancelTreaty) or (MyAction = scDipOffer) or (MyAction = scDipBreak));
     1118  if MyAction = scDipOffer then
     1119    Result := Server(MyAction - sExecute, me, 0, MyOffer)
     1120  else
     1121    Result := Server(MyAction - sExecute, me, 0, nodata^);
    10521122end;
    10531123
    10541124
    10551125initialization
    1056 nodata:=pointer(0);
    1057 RWDataSize:=0;
     1126  nodata := pointer(0);
     1127  RWDataSize := 0;
    10581128
    10591129end.
    1060 
Note: See TracChangeset for help on using the changeset viewer.