Alright, I've been struggling with this code for over a week now and it has been driving me up a proverbial wall.
Basically, I'm using a system of classes for storing variables, but it seems that I can not create an instance of one of them properly, because when I try to access one of the variables, or call a destructor for the class, I get a segmentation fault.
This is the code (sorry for the length). The World class is the one that seems to be the problem:
unit WorldGen;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Dos;
type
TTerrain=class
LandType:string;
Ruggedness:integer;
Elevation:integer;
ElevationType:string;
IsFault,IsVolcano,HasRiver:boolean;
end;
TClimate=class
PossibleTerrain:array[1..5] of string;
ClimateTName,ClimateRName:string;
Temperature,TempSeasonVar:real;
Rain,RainSeasonVar:integer;
DistFromCoast:integer;
WindDir:integer;
RainShadow:boolean;
IsMonsoonal:boolean;
end;
TRegion=class
Terrain:TTerrain;
Territory:string;
RegionName:string;
Climate:TClimate;
Lattitude:real;
RegionalSav:integer;
end;
TContinent=class
Region:array[1..225,1..225] of TRegion;
ContinentName:string;
CivsPresent:integer;
Hemisphere:string;
FaultType:string;
end;
TWorld=class
NoOfRacesPresent:integer;
WorldName:string;
MinSavagery,MinEvil:integer;
WorldSize:integer;
Continent:array[1..5] of TContinent;
end;
procedure WorldGeneration;
var
World:TWorld;
implementation
uses
MenuSystem,NameGen;
var
ContinentTemp:TContinent;
procedure OceanBoundaries;
var
i2,rx,ry,prob:integer;
begin
for rx:=1 to 225 do
begin
ContinentTemp.Region[rx,1].Terrain.LandType:='ocean';
ContinentTemp.Region[rx,225].Terrain.LandType:='ocean';
end;
for ry:=2 to 224 do
begin
ContinentTemp.Region[1,ry].Terrain.LandType:='ocean';
ContinentTemp.Region[225,ry].Terrain.LandType:='ocean';
end;
for i2:=1 to 30 do
for rx:=2 to 224 do
for ry:=2 to 224 do
begin
prob:=0;
if ContinentTemp.Region[rx-1,ry].Terrain.LandType='ocean' then
prob:=prob+20;
if ContinentTemp.Region[rx+1,ry].Terrain.LandType='ocean' then
prob:=prob+20;
if ContinentTemp.Region[rx,ry-1].Terrain.LandType='ocean' then
prob:=prob+20;
if ContinentTemp.Region[rx,ry+1].Terrain.LandType='ocean' then
prob:=prob+20;
if prob>(random(100)+1) then
begin
ContinentTemp.Region[rx,ry].Terrain.LandType:='ocean';
end;
end;
end;
procedure Faultlines(FaultDir:integer);
var
i,rx,ry,prob,NewDir:integer;
begin
prob:=random(4);
case prob of
0:begin
rx:=1; //left
ry:=random(195)+15;
FaultDir:=3;
end;
1:begin
rx:=225; //right
ry:=random(195)+15;
FaultDir:=7;
end;
2:begin
ry:=1; //top
rx:=random(195)+15;
FaultDir:=5;
end;
3:begin
ry:=225; //bottom
rx:=random(195)+15;
FaultDir:=1;
end;
end;
ContinentTemp.Region[rx,ry].Terrain.IsFault:=TRUE;
for i:=1 to 3 do // this section moves the faultline away from the continent edge to prevent premature termination of the main loop
begin
prob:=random(24)+1;
case prob of
1..5:NewDir:=FaultDir-1;
6..15:NewDir:=FaultDir;
16..20:NewDir:=FaultDir+1;
end;
if NewDir=0 then NewDir:=8;
if NewDir=9 then NewDir:=1;
case NewDir of
1:ry:=ry-1;
2:begin
rx:=rx+1;
ry:=ry-1;
end;
3:rx:=rx+1;
4:begin
rx:=rx+1;
ry:=ry+1;
end;
5:ry:=ry+1;
6:begin
rx:=rx-1;
ry:=ry+1;
end;
7:rx:=rx-1;
8:begin
rx:=rx-1;
ry:=ry+1;
end;
end;
if (rx<1) or (ry<1) or (rx>225) or (ry>225) then
break
else
ContinentTemp.Region[rx,ry].Terrain.IsFault:=TRUE;
end;
repeat // main faultline generation loop
prob:=random(24)+1;
case prob of
1..2:NewDir:=FaultDir-2;
3..7:NewDir:=FaultDir-1;
8..17:NewDir:=FaultDir;
18..22:NewDir:=FaultDir+1;
23..24:NewDir:=FaultDir+2;
end;
if NewDir=0 then NewDir:=8;
if NewDir=-1 then NewDir:=7;
if NewDir=9 then NewDir:=1;
case NewDir of
1:ry:=ry-1;
2:begin
rx:=rx+1;
ry:=ry-1;
end;
3:rx:=rx+1;
4:begin
rx:=rx+1;
ry:=ry+1;
end;
5:ry:=ry+1;
6:begin
rx:=rx-1;
ry:=ry+1;
end;
7:rx:=rx-1;
8:begin
rx:=rx-1;
ry:=ry+1;
end;
end;
if ((rx>0) and (rx<226)) and ((ry>0) and (ry<226)) then
ContinentTemp.Region[rx,ry].Terrain.IsFault:=TRUE;
until (rx=225) or (rx=1) or (ry=225) or (ry=1); // this repeats until the continent edge has been hit
prob:=random(10)+1;
case prob of // these affect the probability of volcanoes and earthquakes in surrounding regions.
1..4:ContinentTemp.FaultType:='transform';
5..6:ContinentTemp.FaultType:='subduction';
7..9:ContinentTemp.FaultType:='convergant';
10:ContinentTemp.FaultType:='divergant';
end;
end;
function DistFromFault(rx:integer; ry:integer):real;
var
x,x1,x2,y,y1,y2,rx2,ry2:integer;
Distance:real;
begin
if ContinentTemp.Region[rx,ry].Terrain.IsFault=FALSE then
begin
rx2:=rx;
x1:=0;
x2:=0;
repeat
x1:=x1+1;
rx2:=rx2-1;
until (rx2<2) or (ContinentTemp.Region[rx2,ry].Terrain.IsFault=TRUE);
rx2:=rx;
repeat
x2:=x2+1;
rx2:=rx2+1;
until (rx2>224) or (ContinentTemp.Region[rx2,ry].Terrain.IsFault=TRUE);
ry2:=ry;
y1:=0;
y2:=0;
repeat
y1:=y1+1;
ry2:=ry2-1;
until (ry2<2) or (ContinentTemp.Region[rx,ry2].Terrain.IsFault=TRUE);
ry2:=ry;
repeat
y2:=y2+1;
ry2:=ry2+1;
until (ry2>224) or (ContinentTemp.Region[rx,ry2].Terrain.IsFault=TRUE);
if x1<x2 then
x:=x1
else
x:=x2;
if y1>y2 then
y:=y1
else
y:=y2;
Distance:=sqrt(sqr(x)+sqr(y));
DistFromFault:=Distance;
end
else
DistFromFault:=0;
end;
procedure ElevationMesh;
var
rx,ry,prob,RangeWidth:integer;
Elevation:array[1..225,1..225] of integer;
Dist:real;
begin
{comments go in here}
//create mesh
for rx:=1 to 225 do
for ry:=1 to 225 do
if ContinentTemp.Region[rx,ry].Terrain.LandType='ocean' then
Elevation[rx,ry]:=0
else
Elevation[rx,ry]:=5;
//need mountains, hills and things
RangeWidth:=random(11)+5;
for rx:=1 to 225 do
for ry:=1 to 225 do
begin
if ContinentTemp.Region[rx,ry].Terrain.IsFault=TRUE then
if ContinentTemp.Region[rx,ry].Terrain.LandType<>'ocean' then
case ContinentTemp.FaultType of
'divergant':Elevation[rx,ry]:=random(200)+300;
'convergant':Elevation[rx,ry]:=random(5500)+4000;
'subduction':Elevation[rx,ry]:=random(3000)+1000;
'transform':Elevation[rx,ry]:=random(50)+1;
end
else
begin
prob:=random(100)+1;
if prob>90 then
Elevation[rx,ry]:=random(100)+1
else
Elevation[rx,ry]:=0;
end
else
begin
Dist:=DistFromFault(rx,ry);
if Dist<RangeWidth then
case ContinentTemp.FaultType of
'divergant':Elevation[rx,ry]:=trunc(((random(200)+300)*1.1)/Dist);
'convergant':Elevation[rx,ry]:=trunc(((random(4000)+4000)*1.1)/Dist);
'subduction':Elevation[rx,ry]:=trunc(((random(3000)+1000)*1.1)/Dist);
'transform':Elevation[rx,ry]:=trunc(((random(300)+100)*1.1)/Dist);
end
else Elevation[rx,ry]:=Random(51);
end;
end;
for rx:=1 to 225 do
for ry:=1 to 225 do
ContinentTemp.Region[rx,ry].Terrain.Elevation:=Elevation[rx,ry];
for rx:=1 to 225 do
for ry:=1 to 225 do
case Elevation[rx,ry] of
0:ContinentTemp.Region[rx,ry].Terrain.ElevationType:='open_water';
1..38:ContinentTemp.Region[rx,ry].Terrain.ElevationType:='plain';
39..499:ContinentTemp.Region[rx,ry].Terrain.ElevationType:='hill';
500..2499:ContinentTemp.Region[rx,ry].Terrain.ElevationType:='foothill';
2500..9500:ContinentTemp.Region[rx,ry].Terrain.ElevationType:='mountain';
end;
end;
procedure RiverSystem;
var
i,rx,ry,RiverDir,prob:integer;
IsOcean:boolean;
IsRiver:array[1..225,1..225] of boolean;
begin
for rx:=1 to 225 do
for ry:=1 to 225 do
IsRiver[rx,ry]:=FALSE;
for i:=1 to 50 do
begin
repeat
rx:=random(225)+1;
ry:=random(225)+1;
if ContinentTemp.Region[rx,ry].Terrain.LandType='ocean' then
IsOcean:=TRUE
else
IsOcean:=FALSE;
until IsOcean=FALSE;
RiverDir:=random(8)+1;
repeat
IsRiver[rx,ry]:=TRUE;
prob:=random(9)+1;
case prob of
1:RiverDir:=RiverDir-2;
2..3:RiverDir:=RiverDir-1;
7..8:RiverDir:=RiverDir+1;
9:RiverDir:=RiverDir+2;
end;
if RiverDir>8 then
RiverDir:=RiverDir-8
else if RiverDir<1 then
RiverDir:=RiverDir+8;
case RiverDir of
1:ry:=ry-1;
2:begin
rx:=rx+1;
ry:=ry-1;
end;
3:rx:=rx+1;
4:begin
rx:=rx+1;
ry:=ry+1;
end;
5:ry:=ry+1;
6:begin
rx:=rx-1;
ry:=ry+1;
end;
7:rx:=rx-1;
8:begin
rx:=rx-1;
ry:=ry+1;
end;
end;
if ContinentTemp.Region[rx,ry].Terrain.LandType='ocean' then
IsOcean:=TRUE
else
IsOcean:=FALSE;
until (IsOcean=TRUE) or (ContinentTemp.Region[rx,ry].Terrain.HasRiver=TRUE);
for rx:=1 to 225 do
for ry:=1 to 225 do
ContinentTemp.Region[rx,ry].Terrain.HasRiver:=IsRiver[rx,ry];
end;
end;
procedure ContinentSetup(N:integer);
var
FaultDir,rx,ry:integer;
begin
ContinentTemp:=TContinent.Create;
for rx:=1 to 225 do
for ry:=1 to 225 do
begin
ContinentTemp.Region[rx,ry]:=TRegion.Create;
ContinentTemp.Region[rx,ry].Climate:=TClimate.Create;
ContinentTemp.Region[rx,ry].Terrain:=TTerrain.Create;
end;
FaultDir:=0;
OceanBoundaries;
FaultLines(FaultDir);
ElevationMesh;
RiverSystem;
World.Continent[N]:=ContinentTemp;
for rx:=1 to 225 do
for ry:=1 to 225 do
begin
World.Continent[N].Region[rx,ry]:=ContinentTemp.Region[rx,ry];
World.Continent[N].Region[rx,ry].Climate:=ContinentTemp.Region[rx,ry].Climate;
World.Continent[N].Region[rx,ry].Terrain:=ContinentTemp.Region[rx,ry].Terrain;
ContinentTemp.Region[rx,ry].Climate.Destroy;
ContinentTemp.Region[rx,ry].Climate:=Nil;
ContinentTemp.Region[rx,ry].Terrain.Destroy;
ContinentTemp.Region[rx,ry].Terrain:=Nil;
ContinentTemp.Region[rx,ry].Destroy;
ContinentTemp.Region[rx,ry]:=Nil;
end;
ContinentTemp.Destroy;
ContinentTemp:=Nil;
end;
procedure SaveWorldAtGen;
var
FName:text;
DirPath,DirName,FStr:PathStr;
WriteStr:string;
rx,ry,I:integer;
begin
DirName:='Games\'+World.WorldName;
DirPath:=FSearch(DirName,GetEnv(''));
if DirPath='' then
CreateDir('Games\'+World.WorldName)
else
begin
I:=1;
repeat
I:=I+1;
DirName:='Games\'+World.WorldName+IntToStr(I);
DirPath:=FSearch(DirName,GetEnv(''));
until DirPath='';
CreateDir(DirName);
end;
I:=0;
for I:=1 to World.WorldSize do
begin
FStr:=DirName+'\Continent'+IntToStr(I); //this is just for testing, will export continent name at later stage.
Assign(FName,FStr);
rewrite(FName); //start witing
writeln(FName,'//Elevation:');
for ry:=1 to 225 do
begin
for rx:=1 to 225 do
begin
//WriteStr:=IntToStr(World.Continent[I].Region[rx,ry].Terrain.Elevation); //this line produces a segmentation fault
//write(FName,WriteStr);
write(FName,',');
end;
writeln(FName,'');
end;
Close(FName); //end writing
end;
end;
procedure WorldParameters;
begin
if Form1.ContNoCombo.Text<>'Random' then
World.WorldSize:=StrToInt(Form1.ContNoCombo.Text)
else
World.WorldSize:=random(5)+1;
World.WorldName:=Form1.WorldNameEdit.Text;
//temp
//World.WorldSize:=1;
end;
procedure WorldGeneration;
var
N,rx,ry:integer;
begin
World:=Nil;
World:=TWorld.Create;
for N:=1 to 5 do
begin
World.Continent[N]:=TContinent.Create;
for rx:=1 to 225 do
for ry:=1 to 225 do
begin
World.Continent[N].Region[rx,ry]:=TRegion.Create;
World.Continent[N].Region[rx,ry].Climate:=TClimate.Create;
World.Continent[N].Region[rx,ry].Terrain:=TTerrain.Create;
end;
end;
WorldParameters;
For N:=1 to World.WorldSize do
begin
ContinentSetup(N);
end;
SaveWorldAtGen;
for N:=1 to 5 do
begin
for rx:=1 to 225 do
for ry:=1 to 225 do
begin
World.Continent[N].Region[rx,ry].Climate.Destroy;
World.Continent[N].Region[rx,ry].Terrain.Destroy;
World.Continent[N].Region[rx,ry].Destroy;
World.Continent[N].Region[rx,ry].Climate:=Nil;
World.Continent[N].Region[rx,ry].Terrain:=Nil;
World.Continent[N].Region[rx,ry]:=Nil;
end;
World.Continent[N].Destroy;
World.Continent[N]:=Nil;
end;
World.Destroy;
World:=Nil;
end;
end.