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

📄 outercore.pas

📁 类似文明的游戏源代码。
💻 PAS
📖 第 1 页 / 共 5 页
字号:
{$INCLUDE switches}
//{$DEFINE TEXTLOG}
//{$DEFINE LOADPERF}

unit OuterCore;

interface

uses
Protocol, InnerCore;

const
Version=$000D00;
FirstAICompatibleVersion=$000D00;
FirstBookCompatibleVersion=$000D00;

// notifications
ntCreateWorld=0; ntInitModule=$100; ntInitLocalHuman=$1FF;
ntDLLError=$200; ntAIError=$2FF;
ntClientError=$300;
ntInitPlayers=$400; ntDeactivationMissing=$410;
ntLoadBegin=$500; ntLoadState=$501;
ntEndInfo=$600; ntBackOn=$601; ntBackOff=$602; ntLoadError=$603;
ntStartDone=$700; ntStartGo=$701; ntStartGoRefresh=$702;
ntStartGoRefreshMaps=$703;
ntChangeClient=$800; ntNextPlayer=$810;

// module flags
fMultiple=$02;fBroadcast=$04;fUsed=$08;

// save map tile flags
smOwned=$20; smUnit=$40; smCity=$80;

maxBrain=255;
bixNoTerm=0; bixSuper_Virtual=1; bixTerm=2;
  // < bixTerm -> no active player
  // > bixTerm -> AI

type
TNotifyFunction = procedure(ID: integer);

TBrainInfo= record
  FileName, DLLName, Name, Credits: string; {filename and full name}
  hm, {module handle}
  Flags,
  DataVersion, DataSize: integer;
  Client: TClientCall; {client function address}
  end;

var
// PARAMETERS
bixView: array[0..nPl-1]of integer; {brain index of the players}
Difficulty: array[0..nPl-1]of integer absolute InnerCore.Difficulty; {difficulty}

// READ ONLY
nBrain: integer; {number of brains available}
Brain: array[-1..maxBrain-1] of TBrainInfo; {available brains}
MissingBrain: string;

procedure Init(NotifyFunction: TNotifyFunction);
procedure Done;

procedure StartNewGame(const Path, FileName, Map: string; Newlx, Newly,
  NewLandMass, NewMaxTurn: integer);
function LoadGame(const Path, FileName: string; Turn: integer): boolean;
procedure EditMap(const Map: string; Newlx, Newly, NewLandMass: integer);
procedure DirectHelp(StartHelp: boolean);

procedure ChangeClient;
procedure NextPlayer;
function PreviewMap(lm: integer): pointer;


implementation

uses
CmdList,IPQ,LocalHuman,NoTerm,

Windows,Classes,SysUtils;

const
eMountains=$6000FFFF; // additional return code for server internal use

type
TToWorkList = array[0..INFIN,0..nJob-1] of word;

var
MaxDist: integer;
ToWork: ^TToWorkList; {work left for each tile and job}
Worked: array[0..nPl-1] of integer; {settler work statistics}
Stat: array[0..nStat-1, 0..nPl-1] of ^TChart;


procedure MaskD(var x; Count, Mask: Cardinal); Register;
asm
sub eax,4
@r: and [eax+edx*4],ecx
    dec edx
    jnz @r
end;

function Thurst(p, mix, Loc, MP: integer): integer;
begin
if (RW[p].Model[mix].Domain>=dSea)
  or (RealMap[Loc] and (fCity or fRiver or fCanal)<>0)
  or (RealMap[Loc] and fTerImp=tiIrrigation)
  or (RealMap[Loc] and fTerImp=tiFarm)
  or (RealMap[Loc] and fTerImp=tiBase)
  or (GWonder[woGardens].EffectiveOwner=p) then
  result:=0
else if (RealMap[Loc] and fTerrain=fDesert)
  and (RealMap[Loc] and fSpecial<>fSpecial1{Oasis}) then
  result:=(DesertThurst*MP-1) div RW[p].Model[mix].Speed +1
else if RealMap[Loc] and fTerrain=fArctic then
  result:=(ArcticThurst*MP-1) div RW[p].Model[mix].Speed +1
else result:=0
end;

function UnitSpeed(p, mix, Health: integer): integer;
begin
with RW[p].Model[mix] do
  begin
  result:=Speed;
  if Domain=dSea then
    begin
    if GWonder[woMagellan].EffectiveOwner=p then inc(result,200);
    if Health<100 then
      result:=((result-250)*Health div 5000)*50+250;
    end
  end
end;

procedure GetCityReport(p,cix: integer; var CityReport: TCityReport);
var
i,y0,uix,dx,dy,fix,plus,ProdBonus,TradeBonus,ScienceBonus,PollBonus,FutResBonus,
  FutProdBonus,Dist,Loc1,TerrOwner,ForcedSupport: integer;
RareOK: array[0..3] of integer;
RelCorr: single;
TileInfo:TTileInfo;
PModel: ^TModel;
begin
with RW[p].City[cix], CityReport do
  begin
  if HypoTiles<=0 then HypoTiles:=Tiles;
  if HypoTax<0 then HypoTax:=RW[p].TaxRate;
  if HypoLux<0 then HypoLux:=RW[p].LuxRate;
  Working:=0;
  FoodRep:=0;ProdRep:=0;Trade:=0;
  FillChar(RareOK,SizeOf(RareOK),0);
  y0:=Loc div lx;
  for fix:=0 to 26 do if HypoTiles and (1 shl fix)<>0 then
    begin {sum resources of exploited tiles}
    dy:=fix shr 2-3; dx:=fix and 3 shl 1 -3 + (dy+3) and 1;
    Loc1:=(Loc+(dx+y0 and 1+lx+lx) shr 1) mod lx +lx*(y0+dy);
    GetTileInfo(p,cix,Loc1,TileInfo);
    inc(FoodRep,TileInfo.Food);
    inc(ProdRep,TileInfo.Prod);
    inc(Trade,TileInfo.Trade);
    if (RealMap[Loc1] and fRare<>0) and (RW[p].Tech[adMassProduction]>=tsApplicable) then
      inc(RareOK[RealMap[Loc1] shr 25 and 3]);
    inc(Working)
    end;

  Happy:=BasicHappy;
  if (Built[imColosseum]>0) and (Happy<Working-Size shr 1) then
    Happy:=Working-Size shr 1;
  for i:=0 to 27 do if Built[i]=1 then inc(Happy);
  if Built[imTemple]=1 then inc(Happy);
  if Built[imCathedral]=1 then
    begin
    inc(Happy,2);
    if GWonder[woBach].EffectiveOwner=p then inc(Happy,1)
    end;
  if Built[imTheater]>0 then inc(Happy,2);
  if RW[p].Government=gAnarchy then Happy:=0;

  ProdBonus:=0; TradeBonus:=0; ScienceBonus:=0; PollBonus:=0;
  if Built[imAlgae]=1 then inc(FoodRep,12);
  if Built[imMarket]=1 then inc(TradeBonus);
  if Built[imBank]=1 then
    begin
    inc(TradeBonus,2);
    if RW[p].NatBuilt[imStockEx]=1 then inc(TradeBonus,2);
    end;
  if Built[imLibrary]=1 then inc(ScienceBonus);
  if Built[imUniversity]=1 then inc(ScienceBonus,2);
  if Built[imResLab]=1 then inc(ScienceBonus,3);
  if Built[imFactory]=1 then inc(ProdBonus);
  if Built[imMfgPlant]=1 then inc(ProdBonus);
  if (Built[imPower]=1) or (Built[imHydro]=1)
    or (Built[imNuclear]=1) or (GWonder[woHoover].EffectiveOwner=p) then
    ProdBonus:=ProdBonus*2;
  if Built[imFactory]=1 then inc(PollBonus);
  if Built[imMfgPlant]=1 then inc(PollBonus);
  if (Built[imFactory]+Built[imMfgPlant]>0) then
    if (Built[imHydro]>0)
      or (GWonder[woHoover].EffectiveOwner=p) then dec(PollBonus)
    else if (Built[imNuclear]=0) and (Built[imPower]=1) then inc(PollBonus);
  if (RW[p].Government<=gDespotism) or (Built[imRecycling]=1) then
    PollBonus:=-2; // no pollution

  // future tech benefits
  FutResBonus:=0;
  if RW[p].Tech[futResearchTechnology]>0 then
    begin
    if Built[imUniversity]=1 then
      inc(FutResBonus,UniversityFutureBonus*RW[p].Tech[futResearchTechnology]);
    if Built[imResLab]=1 then
      inc(FutResBonus,ResLabFutureBonus*RW[p].Tech[futResearchTechnology]);
    end;
  FutProdBonus:=0;
  if RW[p].Tech[futProductionTechnology]>0 then
    begin
    if Built[imFactory]=1 then
      inc(FutProdBonus,FactoryFutureBonus*RW[p].Tech[futProductionTechnology]);
    if Built[imMfgPlant]=1 then
      inc(FutProdBonus,MfgPlantFutureBonus*RW[p].Tech[futProductionTechnology]);
    end;

  // calculate unit support
  Support:=0; ForcedSupport:=0; Eaten:=Size*2; Deployed:=0;
  for uix:=0 to RW[p].nUn-1 do with RW[p].Un[uix] do
    if (Loc>=0) and (Home=cix) then
      begin
      PModel:=@RW[p].Model[mix];
      if (PModel.Kind=mkSettler) {and (GWonder[woFreeSettlers].EffectiveOwner<>p)} then
        inc(Eaten,SettlerFood[RW[p].Government])
      else if Flags and unConscripts<>0 then inc(Eaten);

      if (RW[p].Government<>gAnarchy) and (RW[p].Government<>gFundamentalism)
        and ((GWonder[woLiberty].EffectiveOwner<>p) or (RealMap[Loc] and fCity=0)
        or (Movement<UnitSpeed(p,mix,Health))) then
        begin
        if GTestFlags and tfImmImprove=0 then
          if PModel.Kind=mkSpecial_TownGuard then inc(ForcedSupport)
          else if (PModel.Flags and mdDoubleSupport<>0) then inc(Support,2)
          else inc(Support);
        if PModel.Flags and mdCivil=0 then
          begin
          TerrOwner:=RealMap[Loc] shr 27;
          case RW[p].Government of
            gRepublic, gLybertarianism:
              if (TerrOwner<>p) and (TerrOwner<nPl)
                and (RW[p].Treaty[TerrOwner]<trAlliance) then
                inc(Deployed);
            gDemocracy:
              if (TerrOwner>=nPl) or (TerrOwner<>p)
                and (RW[p].Treaty[TerrOwner]<trAlliance) then
                inc(Deployed);
            end;
          end
        end;
      end;
  if Deployed>=Happy then Happy:=0 else dec(Happy,Deployed);
  dec(Support,Size*SupportFree[RW[p].Government] shr 1);
  if Support<0 then Support:=0;
  inc(Support,ForcedSupport);
  if RW[p].Government=gFundamentalism then
    begin Happy:=Working; Science:=Science shr 1 end;

  {police units}
  case RW[p].Government of
    gDespotism:
      for i:=0 to RW[p].nUn-1 do
        if (RW[p].Un[i].Loc=Loc)
          and (RW[p].Model[RW[p].Un[i].mix].Kind=mkSpecial_TownGuard) then
          inc(Happy);
    end;

  Dist:=MaxDist;
  for i:=0 to RW[p].nCity-1 do
    if (RW[p].City[i].Loc>=0) and (RW[p].City[i].Built[imPalace]=1) then
      Dist:=Distance(Loc,RW[p].City[i].Loc);
  if (Dist=0) or (CorrLevel[RW[p].Government]=0) then Corruption:=0
  else
    begin
    RelCorr:=Dist/MaxDist;
    if CorrLevel[RW[p].Government]>1 then
      RelCorr:=Exp(ln(RelCorr)/CorrLevel[RW[p].Government]);
    if Built[imCourt]=1 then RelCorr:=RelCorr/2;
    Corruption:=Trunc(Trade*RelCorr);
    // !!! floating point calculation always deterministic???
    end;

  Tax:=(HypoTax*(Trade-Corruption)+50) div 100;
  if RW[p].Government=gAnarchy then Lux:=0
  else if GWonder[woMich].EffectiveOwner=p then
    begin
    plus:= Working -Size shr 1 -Happy; // required additional happies
    if plus>0 then
      begin
      Lux:=(4*plus +1+TradeBonus) div (2+TradeBonus);
      if Lux>Trade-Corruption then Lux:=Trade-Corruption;
      if Tax>Trade-Corruption-Lux then Tax:=Trade-Corruption-Lux;
      end
    else Lux:=0;
    end
  else if (HypoLux=0) or (HypoTax=100) then Lux:=0
  else Lux:=(HypoLux*(Trade-Corruption-Tax) + (100-HypoTax) shr 1) div (100-HypoTax);
  Science:=Trade-Corruption-Lux-Tax;

  Tax:=Tax*(2+TradeBonus) shr 1;
  Lux:=Lux*(2+TradeBonus) shr 1;
  if FutResBonus>0 then
    Science:=Science*(100+ScienceBonus*50+FutResBonus) div 100
  else Science:=Science*(2+ScienceBonus) shr 1;
  if Built[imNatObs]>0 then Science:=Science*2;
  if RW[p].Government=gFundamentalism then Science:=Science shr 1
  else if (GWonder[woNewton].EffectiveOwner=p) and (RW[p].Government=gMonarchy) then
    Science:=Science*2;
  PollRep:=ProdRep*(2+PollBonus) shr 1;
  if PollRep<=Size then PollRep:=0 else dec(PollRep,Size);
  if FutProdBonus>0 then
    ProdRep:=ProdRep*(100+ProdBonus*50+FutProdBonus) div 100
  else ProdRep:=ProdRep*(2+ProdBonus) shr 1;
  Happy:=Happy+Lux shr 1;
  // if Happy>Working then Happy:=Working;

  // calculate storage size
  Storage:=StorageSize[Difficulty[p]];
//  if RW[p].Government=gLybertarianism then Storage:=Storage*2;

  // check if rare resource available
  if (GTestFlags and tfNoRareNeed=0) and (ProdRep>Support)
    and (Project and cpImp<>0)
    and ((Project and cpIndex=imShipComp) and (RareOK[1]=0)
      or (Project and cpIndex=imShipPow) and (RareOK[2]=0)
      or (Project and cpIndex=imShipHab) and (RareOK[3]=0)) then
    ProdRep:=Support;

  // calculate project cost
  if Project and cpImp=0 then
    begin
    ProdCost:=RW[p].Model[Project and cpIndex].Cost; {unit project}
    if Project and cpConscripts<>0 then
      begin
      i:=RW[p].Model[Project and cpIndex].MCost;
      ProdCost:=ProdCost-3*i;
      if ProdCost<=0 then ProdCost:=i
      end
    else if RW[p].Model[Project and cpIndex].Cap[mcLine]>0 then
      if Project0 and (cpRepeat or cpIndex)=Project and cpIndex or cpRepeat then
        ProdCost:=ProdCost shr 1
      else ProdCost:=ProdCost*2
    end
  else
    begin {improvement project}
    ProdCost:=Imp[Project and cpIndex].Cost;
    if (Project and cpIndex<28) and (GWonder[woColossus].EffectiveOwner=p) then
      ProdCost:=ProdCost*ColossusEffect div 100;
    end;
  ProdCost:=ProdCost*BuildCostMod[Difficulty[p]] div 12;
  end;
end; {GetCityReport}

procedure GetCityAreaInfo(p,Loc: integer; var CityAreaInfo: TCityAreaInfo);
var
dx, dy, fix, Loc1, p1: integer;
begin
with CityAreaInfo do
  begin
  for fix:=0 to 26 do Available[fix]:=faInvalid;
  for dy:=-3 to 3 do for dx:=-3 to 3 do
    if ((dx+dy) and 1=0) and ((dx<>3) and (dx<>-3) or (dy<>3) and (dy<>-3)) then
      begin
      fix:=(dy+3) shl 2+(dx+3) shr 1; {relative tile location code}
      Loc1:=dLoc(Loc,dx,dy);
      if Loc1<0 then Available[fix]:=faPole
      else
        begin
        p1:=RealMap[Loc1] shr 27;
        if (p1<nPl) and (p1<>p) and (RW[p].Treaty[p1]>=trPeace) then
          Available[fix]:=faTreaty
        else if (ZoCMap[Loc1]>0) and (Occupant[Loc1]<>p)
          and (RW[p].Treaty[Occupant[Loc1]]<trAlliance) then
          Available[fix]:=faSiege
        else if (UsedByCity[Loc1]<>-1) and (UsedByCity[Loc1]<>Loc) then
          Available[fix]:=faNotAvailable
        else Available[fix]:=faAvailable
        end
      end;
  end
end;

function SetCityTiles(p, cix, NewTiles: integer; TestOnly: boolean = false): integer;
var
fix,Working,ChangeTiles,AddTiles,dx,dy,Loc1: integer;
CityAreaInfo: TCityAreaInfo;
begin
with RW[p].City[cix] do
  begin
  ChangeTiles:=NewTiles xor integer(Tiles);
  AddTiles:=NewTiles and not Tiles;
  if Mode=moPlaying then
    begin // do all checks
    if NewTiles and not $67F7F76<>0 then
      begin result:=eInvalid; exit end; // invalid tile index included
    if NewTiles and (1 shl 13)=0 then
      begin result:=eViolation; exit end; // city tile must be exploited
    if ChangeTiles=0 then
      begin result:=eNotChanged; exit end;

⌨️ 快捷键说明

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