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

📄 innercore.pas

📁 类似文明的游戏源代码。
💻 PAS
📖 第 1 页 / 共 5 页
字号:
        i:=0;
        while (i<nEnemyCity) and (EnemyCity[i].Loc<>Loc) do
          inc(i);
        if i=nEnemyCity then
          begin
          inc(nEnemyCity);
          assert(nEnemyCity<necmax);
          EnemyCity[i].Status:=0;
          EnemyCity[i].SavedStatus:=0;
          if pTell=p then result:=true;
          end;
        MakeCityInfo(pFoundCity,cixFoundCity,EnemyCity[i]);
        end;
      end
  else if Map[Loc] and fCity<>0 then // remove enemycity
    for cix:=0 to nEnemyCity-1 do
      if EnemyCity[cix].Loc=Loc then
        EnemyCity[cix].Loc:=-1;

  if Map[Loc]=fUNKNOWN then inc(Discovered[pTell]);
  if euix>=-1 then
    Map[Loc]:=Map[Loc] and not (fUnit or fCity or fOwned)
      or Tile and (fUnit or fCity or fOwned)
  else
    begin
    Map[Loc]:=Tile;
    MapObservedLast[Loc]:=GTurn
    end;
  ObserveLevel[Loc]:=ObserveLevel[Loc] and not (3 shl (2*pTell))
    or Cardinal(Level) shl (2*pTell);
  end
end; // DiscoverTile

function Discover(Loc,p,r,AdjacentLevel: integer; TellAllied, EnableContact: boolean): boolean;
{player p discovers at Loc with radius r
result indicates whether new enemy units/cities spotted}
// implementation is critical for loading performance, change carefully
const
table_dy: array[0..41] of integer=
(1,0,2,-1,1,3,-2,0,2,2,-1,1,1,0, //14
2,-1,1,3,-2,0,2,4,-3,-1,1,3,3,-2,0,2,4,-3,-1,1,3,3,-2,0,2,2,-1,1); //28
adjacent: array[0..41] of integer=
(0,1,0,1,1,0,1,1,1,0,1,1,0,1, //14
0,0,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,0); //28
var
i,y0,y,dx,dmax,Loc1,pTell,Level,OldLevel,count,tablestart: integer;
begin
assert((Mode>moLoading_Fast) or (RW[p].nEnemyUn=0));
result:=false;
y0:=Loc div lx;
if r=4 then begin dmax:=3; tablestart:=14 end
else {if r=2 then} begin dmax:=2; tablestart:=0 end;
for dx:=-dmax to dmax do
  begin
  count:=table_dy[tablestart];
  inc(tablestart);
  y:=y0+table_dy[tablestart];
  Loc1:=(Loc+(dx+y0 and 1+lx+lx) shr 1) mod lx +lx*y;
  for i:=0 to count-1 do
    begin
    if (y>=0) and (y<ly) then
      begin
      if adjacent[tablestart]<>0 then Level:=AdjacentLevel
      else Level:=lObserveUnhidden;
      if TellAllied then
        begin
        for pTell:=0 to nPl-1 do
          if (pTell=p) or (1 shl pTell and GAlive<>0)
            and (RW[p].Treaty[pTell]=trAlliance) then
            begin
            OldLevel:=ObserveLevel[Loc1] shr (2*pTell) and 3;
            if Level>OldLevel then
              result:=DiscoverTile(Loc1,p,pTell,Level,EnableContact) or result;
            end
        end
      else
        begin
        OldLevel:=ObserveLevel[Loc1] shr (2*p) and 3;
        if Level>OldLevel then
          result:=DiscoverTile(Loc1,p,p,Level,EnableContact) or result;
        end
      end;
    inc(y,2);
    inc(Loc1,lx+lx);
    inc(tablestart);
    end
  end;
end;

(*unoptimized implementation:
function Discover(Loc,p,r:integer; SpotNearHidden, TellAllied, EnableContact: boolean): boolean;
var
y0,dx,dy,dmax,Loc1,pTell,Loc1x,r1,Level,OldLevel: integer;
begin
result:=false;
y0:=Loc div lx;
if r=4 then dmax:=3
else {if r=2 then} dmax:=2;
for dx:=-dmax to dmax do
  begin
  Loc1x:=(Loc+(dx+y0 and 1+lx+lx) shr 1) mod lx;
  for dy:=-dmax to dmax do
    if ((dx+dy) and 1=0) and (y0+dy>=0) and (y0+dy<ly) then
      begin
      r1:=abs(dx)+abs(dy);
      if r1<=r then
        begin
        Loc1:=Loc1x +lx*(y0+dy);
        if SpotNearHidden and (r1<=2) then Level:=lObserveAll
        else Level:=lObserveUnhidden;
        if TellAllied then
          begin
          for pTell:=0 to nPl-1 do
            if (pTell=p) or (RW[p].Treaty[pTell]=trAlliance) then
              begin
              OldLevel:=ObserveLevel[Loc1] shr (2*pTell) and 3;
              if Level>OldLevel then
                result:=DiscoverTile(Loc1,p,pTell,Level,EnableContact) or result;
              end
          end
        else
          begin
          OldLevel:=ObserveLevel[Loc1] shr (2*p) and 3;
          if Level>OldLevel then
            result:=DiscoverTile(Loc1,p,p,Level,EnableContact) or result;
          end
        end
      end
  end;
end;*)

procedure DiscoverAll(p, Level: integer);
{player p discovers complete playground (for supervisor)}
var
Loc, OldLevel: integer;
begin
assert((Mode>moLoading_Fast) or (RW[p].nEnemyUn=0));
for Loc:=0 to MapSize-1 do
  begin
  OldLevel:=ObserveLevel[Loc] shr (2*p) and 3;
  if Level>OldLevel then
    DiscoverTile(Loc,p,p,Level,false);
  end;
end;

procedure DiscoverViewAreas(p: integer);
var
pTell, uix, cix: integer;
PModel: ^TModel;
begin // discover unit and city view areas
for pTell:=0 to nPl-1 do
  if (pTell=p) or (RW[p].Treaty[pTell]=trAlliance) then
    begin
    for uix:=0 to RW[pTell].nUn-1 do with RW[pTell].Un[uix] do
      if (Loc>=0) and (master<0) then
        begin
        PModel:=@RW[pTell].Model[mix];
        if (PModel.Kind=mkDiplomat) or (PModel.Cap[mcSpy]>0) then
          Discover(Loc,p,4,lObserveSuper,false,true)
        else if (PModel.Cap[mcRadar]+PModel.Cap[mcCarrier]>0)
          or (PModel.Domain=dAir) then
          Discover(Loc,p,4,lObserveAll,false,false)
        else if (RealMap[Loc] and fTerrain=fMountains)
          or (PModel.Cap[mcAcademy]>0) then
          Discover(Loc,p,4,lObserveUnhidden,false,PModel.Domain=dGround)
        else Discover(Loc,p,2,lObserveUnhidden,false,PModel.Domain=dGround);
        end;
    for cix:=0 to RW[pTell].nCity-1 do if RW[pTell].City[cix].Loc>=0 then
      Discover(RW[pTell].City[cix].Loc,p,4,lObserveUnhidden,false,true);
    end;
if GWonder[woMir].EffectiveOwner=p then
  DiscoverAll(p,lObserveUnhidden)
end;

function GetUnitStack(p,Loc: integer): integer;
var
uix: integer;
unx: ^TUn;
begin
result:=0;
if Occupant[Loc]<0 then exit;
for uix:=0 to RW[Occupant[Loc]].nUn-1 do
  begin
  unx:=@RW[Occupant[Loc]].Un[uix];
  if unx.Loc=Loc then
    begin
    MakeUnitInfo(Occupant[Loc],unx^,RW[p].EnemyUn[RW[p].nEnemyUn+result]);
    TellAboutModel(p,Occupant[Loc],unx.mix);
    RW[p].EnemyUn[RW[p].nEnemyUn+result].emix:=RWemix[p,Occupant[Loc],unx.mix];
    inc(result);
    end
  end
end;

procedure UpdateUnitMap(Loc: integer; CityChange: boolean = false);
// update maps and enemy units of all players after unit change
var
p, euix, OldLevel, ClearFlags: integer;
begin
if (Mode=moLoading_Fast) and not CityChange then exit;
for p:=0 to nPl-1 do if 1 shl p and GWatching<>0 then
  begin
  OldLevel:=ObserveLevel[Loc] shr (2*p) and 3;
  if OldLevel>lNoObserve then
    begin
    if RW[p].Map[Loc] and (fUnit or fOwned)=fUnit then
      begin
      // replace unit located here in EnemyUn
      // do not just set loc:=-1 because total number would be unlimited
      euix:=RW[p].nEnemyUn-1;
      while euix>=0 do
        begin
        if RW[p].EnemyUn[euix].Loc=Loc then
          begin RW[p].EnemyUn[euix].Loc:=-1; Break; end;
        dec(euix);
        end;
      RW[p].Map[Loc]:=RW[p].Map[Loc] and not fUnit
      end
    else
      begin // look for empty slot in EnemyUn
      euix:=RW[p].nEnemyUn-1;
      while (euix>=0) and (RW[p].EnemyUn[euix].Loc>=0) do dec(euix);
      end;
    if (Occupant[Loc]<0) and not CityChange then
      begin
      if RealMap[Loc] and fCity=0 then
        ClearFlags:=fUnit or fHiddenUnit or fStealthUnit or fOwned
      else ClearFlags:=fUnit or fHiddenUnit or fStealthUnit;
      RW[p].Map[Loc]:=RW[p].Map[Loc] and not ClearFlags;
      end
    else if (Occupant[Loc]<>p) or CityChange then
      begin
      ObserveLevel[Loc]:=ObserveLevel[Loc] and not (3 shl (2*p));
      DiscoverTile(Loc, p, p, OldLevel, false, euix);
      end
    else {if (Occupant[Loc]=p) and not CityChange then}
      RW[p].Map[Loc]:=RW[p].Map[Loc] or fUnit or fOwned;
    end
  end
end;

{
                         Territory Calculation
 ____________________________________________________________________
}
var
BorderChanges: array[0..sIntExpandTerritory and $F-1] of Cardinal;

procedure ChangeTerritory(Loc, p: integer);
var
p1: integer;
begin
assert(p>=0); // no player's territory indicated by p=nPl
dec(Territory[RealMap[Loc] shr 27]);
inc(Territory[p]);
RealMap[Loc]:=RealMap[Loc] and not fTerritory or Cardinal(p) shl 27;
for p1:=0 to nPl-1 do if 1 shl p1 and GWatching<>0 then
  if ObserveLevel[Loc] and (3 shl (p1*2))>0 then
    RW[p1].Map[Loc]:=RW[p1].Map[Loc] and not fTerritory or Cardinal(p) shl 27;
end;

procedure ExpandTerritory(p, OriginLoc: integer);
var
i,dx,dy,dxMax,dyMax,Loc,NewOwner: integer;
begin
i:=0;
dyMax:=0;
while (dyMax+1)+(dyMax+1) shr 1<=CountryRadius do
  inc(dyMax);
for dy:=-dyMax to dyMax do
  begin
  dxMax:=dy and 1;
  while abs(dy)+(dxMax+2)+abs(abs(dy)-(dxMax+2)) shr 1<=CountryRadius do
    inc(dxMax,2);
  for dx:=-dxMax to dxMax do if (dy+dx) and 1=0 then
    begin
    NewOwner:=BorderChanges[i div 8] shr (i mod 8 *4) and $F;
    Loc:=dLoc(OriginLoc,dx,dy);
    if (Loc>=0) and (Cardinal(NewOwner)<>RealMap[Loc] shr 27) then
      ChangeTerritory(Loc,NewOwner);
    inc(i);
    end
  end
end;

procedure CheckBorders(OriginLoc, PlayerLosingCity: integer);
// OriginLoc: only changes in CountryRadius around this location possible,
//   -1 for complete map, -2 for double-check (no more changes allowed)
// PlayerLosingCity: do nothing but remove tiles no longer in reach from this
//   player's territory, -1 for full border recalculation
var
i,r,Loc,Loc1,Loc1x,dx,dy,p1,p2,cix,NewDist,y0,dxMax,dyMax,OldOwner,
  NewOwner: integer;
AtPeace: array[0..nPl,0..nPl] of boolean;
Country, FormerCountry, {to who's country a tile belongs}
Dist, FormerDist, StolenDist: array[0..lxmax*lymax-1] of ShortInt;
begin
if PlayerLosingCity>=0 then
  begin
  for Loc:=0 to MapSize-1 do StolenDist[Loc]:=CountryRadius+1;
  for cix:=0 to RW[PlayerLosingCity].nCity-1 do
    if RW[PlayerLosingCity].City[cix].Loc>=0 then
      StolenDist[RW[PlayerLosingCity].City[cix].Loc]:=0;

  for r:=1 to CountryRadius shr 1 do
    begin
    move(StolenDist,FormerDist,MapSize);
    for Loc:=0 to MapSize-1 do
      if (FormerDist[Loc]<=CountryRadius-2) // use same conditions as below!
        and ((1 shl (RealMap[Loc] and fTerrain))
        and (1 shl fShore+1 shl fMountains+1 shl fArctic)=0) then
        begin
        y0:=Loc div lx;
        for dx:=-2 to 2 do
          begin
          Loc1x:=(Loc+(dx+y0 and 1+lx+lx) shr 1) mod lx;
          for dy:=-2 to 2 do if abs(dx)+abs(dy)=2 then
            begin
            Loc1:=Loc1x+lx*(y0+dy);
            NewDist:=FormerDist[Loc]+3-dy and 1;
            if (Loc1>=0) and (Loc1<MapSize) and (NewDist<StolenDist[Loc1]) then
              StolenDist[Loc1]:=NewDist;
            end
          end
        end
    end;
  end;

FillChar(Country,MapSize,-1);
for Loc:=0 to MapSize-1 do Dist[Loc]:=CountryRadius+1;
for p1:=0 to nPl-1 do if 1 shl p1 and GAlive<>0 then
  for cix:=0 to RW[p1].nCity-1 do if RW[p1].City[cix].Loc>=0 then
    begin
    Country[RW[p1].City[cix].Loc]:=p1;
    Dist[RW[p1].City[cix].Loc]:=0;
    end;

for r:=1 to CountryRadius shr 1 do
  begin
  move(Country,FormerCountry,MapSize);
  move(Dist,FormerDist,MapSize);
  for Loc:=0 to MapSize-1 do
    if (FormerDist[Loc]<=CountryRadius-2) // use same conditions as above!
      and ((1 shl (RealMap[Loc] and fTerrain))
      and (1 shl fShore+1 shl fMountains+1 shl fArctic)=0) then
      begin
      assert(FormerCountry[Loc]>=0);
      y0:=Loc div lx;
      for dx:=-2 to 2 do
        begin
        Loc1x:=(Loc+(dx+y0 and 1+lx+lx) shr 1) mod lx;
        for dy:=-2 to 2 do if abs(dx)+abs(dy)=2 then
          begin
          Loc1:=Loc1x+lx*(y0+dy);
          NewDist:=FormerDist[Loc]+3-dy and 1;
          if (Loc1>=0) and (Loc1<MapSize) and (NewDist<Dist[Loc1]) then
            begin
            Country[Loc1]:=FormerCountry[Loc];
            Dist[Loc1]:=NewDist;
            end
          end
        end
      end
  end;

FillChar(AtPeace, sizeof(AtPeace), false);
for p1:=0 to nPl-1 do if 1 shl p1 and GAlive<>0 then
  for p2:=0 to nPl-1 do
    if (p2<>p1) and (1 shl p2 and GAlive<>0) and (RW[p1].Treaty[p2]>=trPeace) then
    AtPeace[p1,p2]:=true;

if OriginLoc>=0 then
  begin // update area only
  i:=0; 
  fillchar(BorderChanges, sizeof(BorderChanges), 0);
  dyMax:=0;
  while (dyMax+1)+(dyMax+1) shr 1<=CountryRadius do
    inc(dyMax);
  for dy:=-dyMax to dyMax do
    begin
    dxMax:=dy and 1;
    while abs(dy)+(dxMax+2)+abs(abs(dy)-(dxMax+2)) shr 1<=CountryRadius do
      inc(dxMax,2);
    for dx:=-dxMax to dxMax do if (dy+dx) and 1=0 then
      begin
      Loc:=dLoc(OriginLoc,dx,dy);
      if Loc>=0 then
        begin
        if Loc=2581 then
          Loc:=Loc; //!!!
        OldOwner:=RealMap[Loc] shr 27;
        NewOwner:=Country[Loc] and $f;
        if NewOwner<>OldOwner then
          if AtPeace[NewOwner,OldOwner]
            and not ((OldOwner=PlayerLosingCity) and (StolenDist[Loc]>CountryRadius)) then
            NewOwner:=OldOwner // peace fixes borders
          else ChangeTerritory(Loc,NewOwner);
        inc(BorderChanges[i div 8],NewOwner shl (i mod 8 *4));
        end;
      inc(i);
      end
    end
  end
else for Loc:=0 to MapSize-1 do // update complete map
  begin
  OldOwner:=RealMap[Loc] shr 27;
  NewOwner:=Country[Loc] and $f;
  if (NewOwner<>OldOwner)
    and (not AtPeace[NewOwner,OldOwner]
      or ((OldOwner=PlayerLosingCity) and (StolenDist[Loc]>CountryRadius))) then
    begin
    assert(OriginLoc<>-2); // !!!test if border saving works
    ChangeTerritory(Loc,NewOwner);
    end;
  end;

{$IFOPT O-}if OriginLoc<>-2 then CheckBorders(-2);{$ENDIF} //!!! check: single pass should do!
end; //CheckBorders

procedure LogCheckBorders(p,cix,PlayerLosingCity: integer);
begin
CheckBorders(RW[p].City[cix].Loc,PlayerLosingCity);
IntServer(sIntExpandTerritory,p,cix,

⌨️ 快捷键说明

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