⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 outercore.pas

📁 类似文明的游戏源代码。
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    if AddTiles<>0 then
      begin
      // check if new tiles possible
      GetCityAreaInfo(p, Loc, CityAreaInfo);
      for fix:=1 to 26 do if AddTiles and (1 shl fix)<>0 then
        if CityAreaInfo.Available[fix]<>faAvailable then
          begin result:=eTileNotAvailable; exit end;
      // not more tiles than inhabitants
      Working:=0;
      for fix:=0 to 26 do if NewTiles and (1 shl fix)<>0 then inc(Working);
      if Working>Size then
        begin result:=eNoWorkerAvailable; exit end;
      end;
    end;
  result:=eOK;
  if not TestOnly then
    begin
    for fix:=1 to 26 do if ChangeTiles and (1 shl fix)<>0 then
      begin
      dy:=fix shr 2-3; dx:=fix and 3 shl 1 -3 + (dy+3) and 1;
      Loc1:=dLoc(Loc,dx,dy);
      if NewTiles and (1 shl fix)<>0 then UsedByCity[Loc1]:=Loc // employ tile
      else UsedByCity[Loc1]:=-1 // unemploy tile
      end;
    Tiles:=NewTiles
    end
  end;
end;

function CityGrowth(p,cix: integer): boolean;
var
fix: integer;
AltCityReport:TCityReport;
begin
with RW[p].City[cix] do
  if (Size<MaxCitySize) and ((Size<NeedAqueductSize)
      or (Built[imAqueduct]=1) and (Size<NeedSewerSize)
      or (Built[imSewer]=1)) then
    begin
    inc(Size);
    fix:=NextBest(p,cix);
    if fix>=0 then
      begin {test whether exploitation of fix would lead to disorder}
      AltCityReport.HypoTiles:=Tiles+1 shl fix;
      AltCityReport.HypoTax:=-1;
      AltCityReport.HypoLux:=-1;
      GetCityReport(p,cix,AltCityReport);
      if AltCityReport.Working-AltCityReport.Happy<=Size shr 1 then
        AddCityTile(p,cix,fix) {no disorder -- exploit fix}
      end;
    result:=true
    end
  else result:=false
end;

procedure CityShrink(p,cix: integer);
var
fix, Working: integer;
AltCityReport:TCityReport;
begin
with RW[p].City[cix] do
  begin
  Working:=0;
  for fix:=1 to 26 do if Tiles and (1 shl fix)<>0 then inc(Working);
  dec(Size);
{  if RW[p].Government=gLybertarianism then
    if Food>StorageSize[Difficulty[p]]*2 then Food:=StorageSize[Difficulty[p]]*2
  else else} if Food>StorageSize[Difficulty[p]] then Food:=StorageSize[Difficulty[p]];
  fix:=NextWorst(p,cix);
  if Working>Size then RemoveCityTile(p,cix,fix)
    {all citizens were working -- worst tile no longer exploited}
  else {test whether exploitation of fix would lead to disorder}
    begin
    AltCityReport.HypoTiles:=-1;
    AltCityReport.HypoTax:=-1;
    AltCityReport.HypoLux:=-1;
    GetCityReport(p,cix,AltCityReport);
    if AltCityReport.Working-AltCityReport.Happy>Size shr 1 then
      RemoveCityTile(p,cix,fix) {disorder -- don't exploit fix}
    end;
  end
end;

function Work(p,uix: integer): boolean;
var
uix1,j0,fix: integer;
begin
result:=false;
with RW[p].Un[uix] do if Movement>=100 then
  begin
  if Job>=jRoad then
    if integer(Movement)>=integer(ToWork[Loc,Job]) then {work complete}
      begin
      result:=true;
      if Job<>jIrr then
        Health:=Health-Thurst(p,mix,Loc,ToWork[Loc,Job]);
      dec(Movement,ToWork[Loc,Job]);
      if not (Job in [jCity,jPillage,jPoll]) then
        inc(Worked[p],ToWork[Loc,Job]);
      if Job=jCity then
        begin // found new city
        FoundCity(p,Loc);
        inc(Founded[p]);
        with RW[p].City[RW[p].nCity-1] do
          begin
          ID:=p shl 12+Founded[p]-1;
          Flags:=chFounded;
          end;
        fix:=NextBest(p,RW[p].nCity-1);
        if fix>=0 then AddCityTile(p,RW[p].nCity-1,fix);
        if Mode=moPlaying then LogCheckBorders(p,RW[p].nCity-1);
        RW[p].Un[uix].Health:=0; // causes unit to be removed later
        end
      else CompleteJob(p,Loc,Job);
      ToWork[Loc,Job]:=0;
      j0:=Job;
      for uix1:=0 to RW[p].nUn-1 do
        if (RW[p].Un[uix1].Loc=Loc) and (RW[p].Un[uix1].Job=j0) then
          RW[p].Un[uix1].Job:=jNone
      end
    else
      begin
      dec(ToWork[Loc,Job],Movement);
      if not (Job in [jCity,jPillage,jPoll]) then
        inc(Worked[p],Movement);
      Health:=Health-Thurst(p,mix,Loc,Movement);
      Movement:=0;
      end
  end
end; // work

function GetBattleForecast(Loc: integer; var BattleForecast: TBattleForecast;
  var Duix,Dcix: integer): integer;
var
Time,Defender,AStr,DStr,ABon,DBon,DCnt,Damage:integer;
PModel,DModel: ^TModel;
begin
with BattleForecast do
  begin
  Defender:=Occupant[Loc];
  if (Defender<0) or (Defender=pAtt) then
    begin result:=eOK; exit end; // no attack, simple move

  PModel:=@RW[pAtt].Model[mixAtt];
  if (PModel.Kind=mkDiplomat) and (RealMap[Loc] and fCity<>0) then
    begin result:=eOk; exit end; // spy mission -- return as if move was possible

  if Movement=0 then
    begin result:=eNoTime_Attack; exit end;

  Strongest(Loc,Duix,DStr,DBon,DCnt); {get defense strength and bonus}
  DModel:=@RW[Defender].Model[RW[Defender].Un[Duix].mix];
  if (PModel.Attack=0)
    and not ((PModel.Cap[mcBombs]>0) and (FlagsAtt and unBombsLoaded<>0)
    and (DModel.Domain<dAir)) then
    begin result:=eInvalid; exit end;
  if (RealMap[Loc] and fCity=0) and (RealMap[Loc] and fTerImp<>tiBase) then
    begin
    if (DModel.Cap[mcSub]>0)
      and (RealMap[Loc] and fTerrain<fGrass)
      and (ObserveLevel[Loc] shr (2*pAtt) and 3<lObserveAll) then
      begin result:=eHiddenUnit; exit; end; //attacking submarine not allowed
    if (DModel.Cap[mcStealth]>0)
      and (ObserveLevel[Loc] shr (2*pAtt) and 3<>lObserveSuper) then
      begin result:=eStealthUnit; exit; end; //attacking stealth aircraft not allowed
    if (DModel.Domain=dAir) and (DModel.Kind<>mkSpecial_Glider)
      and (PModel.Domain<>dAir) then
      begin result:=eDomainMismatch; exit end; //can't attack plane
    end;
  if (PModel.Cap[mcLongRange]=0)
    and ((PModel.Domain<dSea) and (RealMap[Loc] and fTerrain<fGrass)
    or (PModel.Domain=dSea) and (RealMap[Loc] and fTerrain>=fGrass)) then
    begin result:=eDomainMismatch; exit end;

  if RW[pAtt].Treaty[Defender]>=trPeace then
    begin
    if (DModel.Kind=mkDiplomat) and (PModel.Domain=dGround)
      and (PModel.Attack>0) and (integer(RealMap[Loc] shr 27)=pAtt) then
      if Movement>=100 then
        begin // expel friendly spy
        EndHealthDef:=RW[Defender].Un[Duix].Health;
        EndHealthAtt:=HealthAtt;
        result:=eExpelled
        end
      else result:=eNoTime_Expel
    else result:=eTreaty;
    exit;
    end;

  // calculate defender strength
  if RealMap[Loc] and fCity<>0 then
    begin // consider city improvements
    SearchCity(Loc,Defender,Dcix);
    if (PModel.Domain<dSea) and (PModel.Cap[mcLongRange]=0)
      and ((RW[Defender].City[Dcix].Built[imWalls]=1)
      or (Continent[RW[Defender].City[Dcix].Loc]=GrWallContinent[Defender])) then
      inc(DBon,8)
    else if (PModel.Domain=dSea)
      and (RW[Defender].City[Dcix].Built[imCoastalFort]=1) then
      inc(DBon,4)
    else if (PModel.Domain=dAir)
      and (RW[Defender].City[Dcix].Built[imMissileBat]=1) then
      inc(DBon,4);
    if RW[Defender].City[Dcix].Built[imBunker]=1 then
      inc(DBon,4)
    end;
  if (PModel.Domain=dAir) and (DModel.Cap[mcAirDef]>0) then
    inc(DBon,4);
  DStr:=DModel.Defense*DBon*100;
  if (DModel.Domain=dAir) and ((RealMap[Loc] and fCity<>0)
    or (RealMap[Loc] and fTerImp=tiBase)) then
    DStr:=0;
  if (DModel.Domain=dSea) and (RealMap[Loc] and fTerrain>=fGrass) then
    DStr:=DStr shr 1;

  // calculate attacker strength
  if PModel.Cap[mcWill]>0 then Time:=100
  else begin Time:=Movement; if Time>100 then Time:=100; end;
  ABon:=4+ExpAtt div ExpCost;
  AStr:=PModel.Attack;
  if (FlagsAtt and unBombsLoaded<>0) and (DModel.Domain<dAir) then // use bombs
    AStr:=AStr+PModel.Cap[mcBombs]*PModel.MStrength*2;
  AStr:=Time*AStr*ABon;

  // calculate damage for defender
  if DStr=0 then Damage:=100
  else
    begin
    Damage:=HealthAtt*AStr div DStr;
    if PModel.Cap[mcFanatic]>0 then Damage:=Damage*2;
    if Damage=0 then Damage:=1;
    end;
  EndHealthDef:=RW[Defender].Un[Duix].Health-Damage;
  if EndHealthDef<0 then EndHealthDef:=0;

  // calculate damage for attacker
  if AStr=0 then Damage:=100
  else
    begin
    Damage:=RW[Defender].Un[Duix].Health*DStr div AStr;
    if DModel.Cap[mcFanatic]>0 then Damage:=Damage*2;
    if PModel.Cap[mcFirst]>0 then Damage:=Damage shr 1;
    if Damage=0 then Damage:=1;
    end;
  Time:=Movement; if Time>100 then Time:=100;
  EndHealthAtt:=HealthAtt-Damage-Thurst(pAtt,mixAtt,Loc,Time);
  if EndHealthAtt<0 then EndHealthAtt:=0;

  if EndHealthDef>0 then result:=eLost
  else if EndHealthAtt>0 then result:=eWon
  else result:=eBloody
  end
end;


var
MaxTurn,
LoadTurn, {turn where to stop loading}
nLogOpened, {nLog of opened book}
{$IFOPT O-}nHandoverStack,{$ENDIF}
LastEndClientCommand,
pContacted, // player contacted for negotiation
pDipActive, // player who's to speak in a negotiation
pTurn, {player who's turn it is}
GWinner,
GColdWarStart,
GStealFrom,
SpyMission,
ZOCTile,
CCCommand,
CCPlayer: integer;
DebugMap: pointer;
AutoSaveState: TCmdListState;
MapField: ^Cardinal; // predefined map
LastOffer: TOffer;
CCData: array[0..14] of integer;
DevModelTurn, {turn of last call to sResetModel}
bix, {brain index of the players}
OriginalDataVersion: array[0..nPl-1] of integer;
SavedData: array[0..nPl-1] of pointer;
HomeDir,
LogFileName, SavePath, {name of file for saving the current game}
MapFileName, // name of map to use, empty for random
AICredits: string;
Notify: TNotifyFunction;
PerfFreq, LastClientTime: int64;
{$IFOPT O-}HandoverStack: array[0..31] of Cardinal;{$ENDIF}
AutoSaveExists,
LoadOK, WinOnAlone, PreviewElevation: boolean;

const
PreviewRND=41601260; {randseed for preview map}

ContraJobs: array[0..nJob-1] of Set of 0..nJob-1=
([],                             //jNone
[jCity],                         //jRoad
[jCity],                         //jRR
[jCity,jTrans],                  //jClear
[jCity,jFarm,jAfforest,jMine,jBase,jFort],         //jIrr
[jCity,jIrr,jAfforest,jMine,jBase,jFort],         //jFarm
[jCity,jIrr,jFarm,jTrans],       //jAfforest
[jCity,jTrans,jIrr,jFarm,jBase,jFort],       //jMine
[jCity,jTrans],                  //jCanal
[jCity,jClear,jAfforest,jMine,jCanal], //jTrans
[jCity,jIrr,jFarm,jMine,jBase],                         //jFort
[jCity],                         //jPoll
[jCity,jIrr,jFarm,jMine,jFort],                         //jBase
[jCity],                         //jPillage
[jRoad..jPillage]);              //jCity

function Server(Command,Player,Subject:integer;var Data): integer; stdcall; forward;


procedure Init(NotifyFunction: TNotifyFunction);
var
i,TestVersion: integer;
f: TSearchRec;
T: TextFile;
s: string;

begin
Notify:=NotifyFunction;
PreviewElevation:=false;

{get available brains}
Brain[bixNoTerm].FileName:=':AIT';
Brain[bixNoTerm].Flags:=0;
Brain[bixNoTerm].Client:=nil;
Brain[bixSuper_Virtual].FileName:=':Supervisor';
Brain[bixSuper_Virtual].Flags:=0;
Brain[bixSuper_Virtual].Client:=nil;
Brain[bixTerm].FileName:=':StdIntf';
Brain[bixTerm].Flags:=fMultiple;
Brain[bixTerm].Client:=nil;
nBrain:=3;
if FindFirst(HomeDir+'*.ai.txt',$21,f)=0 then
  repeat
    with Brain[nBrain] do
      begin
      FileName:=Copy(f.Name,1,Length(f.Name)-7);
      DLLName:=HomeDir+FileName;
      Name:=Copy(f.Name,1,Length(f.Name)-7);
      Credits:='';
      Flags:=0;
      Client:=nil;
      TestVersion:=0;
      AssignFile(T,HomeDir+f.Name);
      Reset(T);
      while not EOF(T) do
        begin
        ReadLn(T,s);
        if Copy(s,1,5)='#NAME' then Name:=Copy(s,7,255)
        else if Copy(s,1,9)='#MULTIPLE' then
          Flags:=Flags or fMultiple
        else if Copy(s,1,10)='#BROADCAST' then
          Flags:=Flags or fBroadcast
        else if Copy(s,1,5)='#PATH' then
          DLLName:=HomeDir+Copy(s,7,255)
        else if Copy(s,1,12)='#GAMEVERSION' then
          for i:=13 to Length(s) do
            case s[i] of
              '0'..'9': TestVersion:=TestVersion and $FFFF00
                +TestVersion and $FF *10+ord(s[i])-48;
              '.': TestVersion:=TestVersion shl 8;
              end
        else if Copy(s,1,8)='#CREDITS' then
          Credits:=Copy(s,10,255)
        end;
      CloseFile(T);
      end;
    if (TestVersion>=FirstAICompatibleVersion) and (TestVersion<=Version) then
      inc(nBrain);
  until FindNext(f)<>0;
end;

procedure Done;
var
i: integer;
begin
for i:=1 to nBrain-1 do if @Brain[i].Client<>nil then
  begin
  Brain[i].Client(cReleaseModule,-1,nil^);
  if i>1 then FreeLibrary(Brain[i].hm);
  end;
end;

function PreviewMap(lm: integer): pointer;
begin
lx:=lxmax; ly:=lymax; MapSize:=lx*ly;
LandMass:=lm;
RandSeed:=PreviewRND;
if not PreviewElevation then
  begin
  CreateElevation;
  PreviewElevation:=true;
  end;
CreateMap(true);
result:=@RealMap;
end;

procedure ChangeClientWhenDone(Command, Player: integer; var Data;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -