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

📄 innercore.pas

📁 类似文明的游戏源代码。
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  end;
end;

{
                          Location Navigation
 ____________________________________________________________________
}
function dLoc(Loc,dx,dy: integer): integer;
{relative location, dx in hor and dy in ver direction from Loc}
var
y0: integer;
begin
assert((Loc>=0) and (Loc<MapSize) and (dx+lx>=0));
y0:=Loc div lx;
result:=(Loc+(dx+y0 and 1+lx+lx) shr 1) mod lx +lx*(y0+dy);
if (result<0) or (result>=MapSize) then result:=-1;
end;

procedure dxdy(Loc0,Loc1: integer; var dx,dy: integer);
begin
dx:=((Loc1 mod lx *2 +Loc1 div lx and 1)
  -(Loc0 mod lx *2 +Loc0 div lx and 1)+3*lx) mod (2*lx) -lx;
dy:=Loc1 div lx-Loc0 div lx;
end;

function Distance(Loc0,Loc1: integer): integer;
var
dx,dy: integer;
begin
dxdy(Loc0,Loc1,dx,dy);
dx:=abs(dx);
dy:=abs(dy);
result:=dx+dy+abs(dx-dy) shr 1;
end;

{
                             Map Creation
 ____________________________________________________________________
}
var
primitive: integer;
StartLoc, StartLoc2: array[0..nPl-1] of integer; {starting coordinates}
Elevation: array[0..lxmax*lymax-1] of Byte; {map elevation}
ElCount: array[Byte] of integer; {count of elevation occurance}

procedure CalculatePrimitive;
var
i,j: integer;
begin
primitive:=1;
i:=2;
while i*i<=MapSize+1 do // test whether prime
  begin if (MapSize+1) mod i=0 then primitive:=0; inc(i) end;

if primitive>0 then
  repeat
    inc(primitive);
    i:=1;
    j:=0;
    repeat inc(j); i:=i*primitive mod (MapSize+1) until (i=1) or (j=MapSize+1);
  until j=MapSize;
end;

function MapGeneratorAvailable: boolean;
begin
result:=(primitive>0) and (lx>=20) and (ly>=40)
end;

procedure CreateElevation;
const
d=64;
Smooth=0.049;{causes low amplitude of short waves}
Detail=0.095;{causes short period of short waves}
Merge=5;{elevation merging range at the connection line of the
  round world,in relation to lx}

var
sa,ca,f1,f2:array[1..d] of single;
imerge,x,y:integer;
v,maxv:single;

  function Value(x,y:integer):single;{elevation formula}
  var
  i:integer;
  begin
  result:=0;
  for i:=1 to d do result:=result+sin(f1[i]*((x*2+y and 1)*sa[i]+y*1.5*ca[i]))
    *f2[i];
   {x values effectively multiplied with 2 to get 2 horizantal periods
   of the prime waves}
  end;

begin
for x:=1 to d do {prepare formula parameters}
  begin
  if x=1 then v:=pi/2 else v:=Random*2*pi;{first wave goes horizontal}
  sa[x]:=sin(v)/lx;
  ca[x]:=cos(v)/ly;
  f1[x]:=2*pi*Exp(Detail*(x-1));
  f2[x]:=Exp(-x*Smooth)
  end;

imerge:=2*lx div Merge;
FillChar(ElCount,SizeOf(ElCount),0);
maxv:=0;
for x:=0 to lx-1 do for y:=0 to ly-1 do
  begin
  v:=Value(x,y);
  if x*2<imerge then v:=(x*2*v+(imerge-x*2)*Value(x+lx,y))/imerge;
  v:=v-sqr(sqr(2*y/ly-1));{soft cut at poles}
  if v>maxv then maxv:=v;

  if v<-4 then Elevation[x+lx*y]:=0
  else if v>8.75 then Elevation[x+lx*y]:=255
  else Elevation[x+lx*y]:=Round((v+4)*20);
  inc(ElCount[Elevation[x+lx*y]])
  end;
end;

procedure FindContinents;

  procedure ReplaceCont(a,b,Stop:integer);
  {replace continent name a by b}
  // make sure always continent[loc]<=loc
  var
  i: integer;
  begin
  if a<b then begin i:=a; a:=b; b:=i end;
  if a>b then
    for i:=a to Stop do if Continent[i]=a then Continent[i]:=b
  end;

var
x,y,Loc,Wrong:integer;
begin
for y:=1 to ly-2 do for x:=0 to lx-1 do
  begin
  Loc:=x+lx*y;
  Continent[Loc]:=-1;
  if RealMap[Loc] and fTerrain>=fGrass then
    begin
    if (y-2>=1) and (RealMap[Loc-2*lx] and fTerrain>=fGrass) then
      Continent[Loc]:=Continent[Loc-2*lx];
    if (x-1+y and 1>=0) and (y-1>=1)
      and (RealMap[Loc-1+y and 1-lx] and fTerrain>=fGrass) then
      Continent[Loc]:=Continent[Loc-1+y and 1-lx];
    if (x+y and 1<lx) and (y-1>=1)
      and (RealMap[Loc+y and 1-lx] and fTerrain>=fGrass) then
      Continent[Loc]:=Continent[Loc+y and 1-lx];
    if (x-1>=0) and (RealMap[Loc-1] and fTerrain>=fGrass) then
      if Continent[Loc]=-1 then Continent[Loc]:=Continent[Loc-1]
      else ReplaceCont(Continent[Loc-1],Continent[Loc],Loc);
    if Continent[Loc]=-1 then Continent[Loc]:=Loc
    end
  end;

{connect continents due to round earth}
for y:=1 to ly-2 do if RealMap[lx*y] and fTerrain>=fGrass then
  begin
  Wrong:=-1;
  if RealMap[lx-1+lx*y] and fTerrain>=fGrass then Wrong:=Continent[lx-1+lx*y];
  if (y and 1=0) and (y-1>=1) and (RealMap[lx-1+lx*(y-1)] and fTerrain>=fGrass) then
    Wrong:=Continent[lx-1+lx*(y-1)];
  if (y and 1=0) and (y+1<ly-1)
    and (RealMap[lx-1+lx*(y+1)] and fTerrain>=fGrass) then
    Wrong:=Continent[lx-1+lx*(y+1)];
  if Wrong>=0 then ReplaceCont(Wrong,Continent[lx*y],MapSize-1)
  end;
end;

procedure RarePositions;
// distribute rare resources
// must be done after FindContinents
var
i,j,Cnt,x,y,dx,dy,Loc0,Loc1,xworst,yworst,totalrare,RareMaxWater,RareType,
  iBest,jbest,MinDist,xBlock,yBlock: integer;
AreaCount, RareByArea, RareAdjacent: array[0..7,0..4] of integer;
RareLoc: array[0..11] of integer;
Dist: array[0..11,0..11] of integer;
begin
RareMaxWater:=0;
repeat
  FillChar(AreaCount, SizeOf(AreaCount), 0);
  for y:=1 to ly-2 do
    begin
    yBlock:=y*5 div ly;
    if yBlock=(y+1)*5 div ly then for x:=0 to lx-1 do
      begin
      xBlock:=x*8 div lx;
      if xBlock=(x+1)*8 div lx then
        begin
        Loc0:=x+lx*y;
        if (RealMap[Loc0] and fTerrain>=fGrass) and (RealMap[Loc0] and fSpecial=0) then
          begin
          Cnt:=0;
          for dy:=-2 to 2 do for dx:=-2 to 2 do
            if abs(dx)+abs(dy)=2 then
              begin
              Loc1:=dLoc(Loc0,dx,dy);
              if (Loc1>=0) and (RealMap[Loc1] and fTerrain<fGrass) then
                inc(Cnt); // count adjacent water
              end;
          if Cnt<=RareMaxWater then // inner land
            begin
            inc(AreaCount[xBlock,yBlock]);
            if Random(AreaCount[xBlock,yBlock])=0 then
              RareByArea[xBlock,yBlock]:=Loc0
            end
          end;
        end;
      end
    end;
  totalrare:=0;
  for x:=0 to 7 do for y:=0 to 4 do if AreaCount[x,y]>0 then
    inc(totalrare);
  inc(RareMaxWater);
until totalrare>=12;

while totalrare>12 do
  begin // remove rarebyarea resources too close to each other
  FillChar(RareAdjacent,SizeOf(RareAdjacent),0);
  for x:=0 to 7 do for y:=0 to 4 do if AreaCount[x,y]>0 then
    begin
    if (AreaCount[(x+1) mod 8,y]>0)
      and (Continent[RareByArea[x,y]]=Continent[RareByArea[(x+1) mod 8,y]]) then
      begin
      inc(RareAdjacent[x,y]);
      inc(RareAdjacent[(x+1) mod 8,y]);
      end;
    if y<4 then
      begin
      if (AreaCount[x,y+1]>0)
        and (Continent[RareByArea[x,y]]=Continent[RareByArea[x,y+1]]) then
        begin
        inc(RareAdjacent[x,y]);
        inc(RareAdjacent[x,y+1]);
        end;
      if (AreaCount[(x+1) mod 8,y+1]>0)
        and (Continent[RareByArea[x,y]]=Continent[RareByArea[(x+1) mod 8,y+1]]) then
        begin
        inc(RareAdjacent[x,y]);
        inc(RareAdjacent[(x+1) mod 8,y+1]);
        end;
      if (AreaCount[(x+7) mod 8,y+1]>0)
        and (Continent[RareByArea[x,y]]=Continent[RareByArea[(x+7) mod 8,y+1]]) then
        begin
        inc(RareAdjacent[x,y]);
        inc(RareAdjacent[(x+7) mod 8,y+1]);
        end;
      end
    end;
  xworst:=0; yworst:=0;
  Cnt:=0;
  for x:=0 to 7 do for y:=0 to 4 do if AreaCount[x,y]>0 then
    begin
    if (Cnt=0) or (RareAdjacent[x,y]>RareAdjacent[xworst,yworst]) then
      begin xworst:=x; yworst:=y; Cnt:=1 end
    else if (RareAdjacent[x,y]=RareAdjacent[xworst,yworst]) then
      begin
      inc(Cnt);
      if Random(Cnt)=0 then begin xworst:=x; yworst:=y; end
      end;
    end;
  AreaCount[xworst,yworst]:=0;
  dec(totalrare)
  end;

Cnt:=0;
for x:=0 to 7 do for y:=0 to 4 do if AreaCount[x,y]>0 then
  begin RareLoc[Cnt]:=RareByArea[x,y]; inc(Cnt) end;
for i:=0 to 11 do
  begin
  RealMap[RareLoc[i]]:=RealMap[RareLoc[i]] or fRare;
  for dy:=-1 to 1 do for dx:=-1 to 1 do if (dx+dy) and 1=0 then
    begin
    Loc1:=dLoc(RareLoc[i],dx,dy);
    if (Loc1>=0) and (RealMap[Loc1] and fTerrain=fMountains) then
      RealMap[Loc1]:=RealMap[Loc1] and not fTerrain or fHills;
    end
  end;
for i:=0 to 11 do for j:=0 to 11 do
  Dist[i,j]:=Distance(RareLoc[i],RareLoc[j]);

MinDist:=Distance(0,MapSize-lx shr 1) shr 1;
for RareType:=1 to 3 do
  begin
  Cnt:=0;
  for i:=0 to 11 do if RareLoc[i]>=0 then
    for j:=0 to 11 do if RareLoc[j]>=0 then
      if (Cnt>0) and (Dist[iBest,jbest]>=MinDist) then
        begin
        if Dist[i,j]>=MinDist then
          begin
          inc(Cnt);
          if Random(Cnt)=0 then
            begin iBest:=i; jbest:=j end
          end
        end
      else if (Cnt=0) or (Dist[i,j]>Dist[iBest,jbest]) then
        begin iBest:=i; jbest:=j; Cnt:=1; end;
  RealMap[RareLoc[iBest]]:=RealMap[RareLoc[iBest]] or Cardinal(RareType) shl 25;
  RealMap[RareLoc[jbest]]:=RealMap[RareLoc[jbest]] or Cardinal(RareType) shl 25;
  RareLoc[iBest]:=-1;
  RareLoc[jbest]:=-1;
  end;
end; // RarePositions

function CheckShore(Loc: integer): boolean;
var
dx,dy,Loc1,OldTile: integer;
begin
result:=false;
OldTile:=RealMap[Loc];
if OldTile and fTerrain<fGrass then
  begin
  RealMap[Loc]:=RealMap[Loc] and not fTerrain or fOcean;
  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
    Loc1:=dLoc(Loc,dx,dy);
    if (Loc1>=0) and (RealMap[Loc1] and fTerrain>=fGrass)
      and (RealMap[Loc1] and fTerrain<>fArctic) then
      RealMap[Loc]:=RealMap[Loc] and not fTerrain or fShore;
    end;
  if (RealMap[Loc] xor Cardinal(OldTile)) and fTerrain<>0 then
    result:=true
  end;
end;

function SpecialTile(Loc: integer): Cardinal;
begin
result:=HypoSpecialTile(Loc mod lx, Loc div lx, RealMap[Loc] and fTerrain);
end;

procedure CreateMap(preview: boolean);
const
ShHiHills=6; {of land}
ShMountains=6; {of land}
ShRandHills=12; {of land}
ShTestRiver=40;
ShSwamp=25; {of grassland}
MinRivLen=3;
unification=70;
hotunification=50; // min. 25

Zone:array[0..3,2..9] of single= {terrain distribution}
 ((0.25,0,   0,   0.4 ,0,0,0,0.35),
  (0.55,0,   0.1 ,0,   0,0,0,0.35),
  (0.4, 0,   0.35,0,   0,0,0,0.25),
  (0,   0.7, 0,   0,   0,0,0,0.3));
  {Grs  Dst  Pra  Tun  - - - For}

  function RndLow(y:integer):Cardinal;
  {random lowland appropriate to climate}
  var
  z0,i:integer;
  p,p0,ZPlus:single;
  begin
  if ly-1-y>y then begin z0:=6*y div ly;ZPlus:=6*y/ly -z0 end
  else begin z0:=6*(ly-1-y) div ly;ZPlus:=6*(ly-1-y)/ly -z0 end;
  p0:=1;
  for i:=2 to 9 do
    begin
    p:=Zone[z0,i]*(1-ZPlus)+Zone[z0+1,i]*ZPlus;
    {weight between zones z0 and z0+1}
    if Random*p0<p then begin RndLow:=i;Break end;
    p0:=p0-p
    end;
  end;

  function RunRiver(Loc0: integer): integer;
  {runs river from start point Loc0; return value: length}
  var
  Dir,T,Loc,Loc1,Cost: integer;
  Q: TIPQ;
  From: array[0..lxmax*lymax-1] of integer;
  Time: array[0..lxmax*lymax-1] of integer;
  OneTileLake: boolean;
  begin
  FillChar(Time,SizeOf(Time),255); {-1}
  Q:=TIPQ.Create(MapSize);
  Q.Put(Loc0,0);
  while Q.Get(Loc,T) and (RealMap[Loc] and fRiver=0) do
    begin
    if (RealMap[Loc] and fTerrain<fGrass) then
      begin
      OneTileLake:=true;
      for Dir:=0 to 3 do
        begin
        Loc1:=dLoc(Loc,Dir and 1 *2 -1,Dir shr 1 *2 -1);
        if (Loc1>=0) and (RealMap[Loc1] and fTerrain<fGrass) then
          OneTileLake:=false;
        end;
      if not OneTileLake then Break;
      end;
    Time[Loc]:=T;
    for Dir:=0 to 3 do
      begin
      Loc1:=dLoc(Loc,Dir and 1 *2 -1,Dir shr 1 *2 -1);
      if (Loc1>=lx) and (Loc1<lx*(ly-1)) and (Time[Loc1]<0) then
        begin
        if RealMap[Loc1] and fRiver=0 then
          begin
          Cost:=Elevation[Loc1]-Elevation[Loc];
          if Cost<0 then Cost:=0;
          end
        else Cost:=0;
        if Q.Put(Loc1,T+Cost shl 8+1) then From[Loc1]:=Loc
        end
      end
    end;
  Loc1:=Loc;
  result:=0;
  while Loc<>Loc0 do begin Loc:=From[Loc]; inc(result); end;
  if (result>1) and ((result>=MinRivLen) or (RealMap[Loc1] and fTerrain>=fGrass)) then
    begin
    Loc:=Loc1;
    while Loc<>Loc0 do
      begin
      Loc:=From[Loc];
      if RealMap[Loc] and fTerrain in [fHills,fMountains] then
        RealMap[Loc]:=fGrass or fRiver
      else if RealMap[Loc] and fTerrain>=fGrass then

⌨️ 快捷键说明

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