program Villages900;
{$mode objfpc}{$H+}
{$IFDEF MSWINDOWS}
{$APPTYPE CONSOLE}
{$ENDIF}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
Classes, sysutils
{ you can add units after this };
type
Tgtt = Array [1..3] of String;
Village = Record
Name, Inn, Government : String;
Gods, Taverns, Trade : Tgtt;
Population, Families, Farmers, Artisans, Laborers, Paupers : Integer;
end; {type Village}
var
Filename : Textfile; // Global Vairable
Recds : Integer; // Global Vairable
Fileline : Array [1..1000] of String; // Global Vairable
Villages : Array [1..1000] of Village; // Global Vairable
iCnt, iCnt2: Integer;
Procedure GetVillageLines; // Reading the raw villages into the string Fileline.
Begin
Assignfile(FileName, '900Vills.txt');
Recds :=1;
Try
Reset(filename);
While not EOF(Filename) do
Begin
ReadLn(filename, Fileline[Recds]);
Fileline[Recds]:=Trim(Fileline[Recds]);
Recds := Recds + 1;
end; {While}
finally
end; {Try}
End; {Proc GetVillageLines}
Procedure Convert;
Var x, iPos: Integer;
sTempLine, sPart: String;
// Get next part where dot is separator.
procedure GetNextPart(var ALine: String; var APart: String);
var iPos2: Integer;
begin
iPos2 := Pos('.', ALine);
If iPos2 > 0 then begin
APart := Copy(ALine, 1, iPos2 - 1);
Delete(ALine, 1, iPos2);
end
else begin
APart := ALine;
ALine := '';
end;
end;
// separate parts combined by ',' or ' and '
// I complicated it because I don't know if combination of 'and' and ',' are possible
// This could probably be simplified
procedure SeparatePart(APartValue: String; var AArray: Tgtt);
var i, iComma, iAnd: Integer;
procedure GetPartValue(APos, ASeparatorLength: Integer);
begin
AArray[i] := Copy(APartValue, 1, APos - 1);
inc(i);
Delete(APartValue, 1, APos + ASeparatorLength);
end;
begin
i := 1;
iComma := Pos(',', APartValue);
iAnd := Pos(' and ', APartValue);
repeat
If iComma = 0 then begin
If iAnd = 0 then begin
AArray[i] := APartValue; // no comma no and
APartValue := '';
end
else
GetPartValue(iAnd, 4); // only and
end
else begin
If iAnd = 0 then
GetPartValue(iComma, 1) // only comma
else
If iAnd > iComma then
GetPartValue(iComma, 1) // comma is first
else
GetPartValue(iAnd, 4); // and is first
end;
iComma := Pos(',', APartValue);
iAnd := Pos(' and ', APartValue);
until (iComma = 0) and (iAnd = 0) and (APartValue = '');
end;
Begin
For x := 1 to Recds do Begin
sTempLine := Fileline[x];
// first part is guaranteed: name, population, families
GetNextPart(sTempLine, sPart);
iPos := Pos(' - Pop ', sPart); // This string is the first guaranteed separator.
Villages[x].Name := Copy(sPart, 1, iPos - 1); // Put the name in the Record.
Villages[x].Population := StrToInt(Trim(Copy(sPart, iPos + 7, 3))); // Population is also always
// a set distance from the above separator.
Villages[x].Families := StrToInt(Trim(Copy(sPart, Pos('(', sPart) + 1, 2))); // Families is always enclosed by parenthesis.
// other parts
While sPart <> '' do begin
If Pos('Gov:', sPart) > 0 then // Government part
Villages[x].Government := Copy(sPart, Pos('Gov:', sPart) + 5, MaxInt)
else
If Pos('Inn: ', sPart) > 0 then
Villages[x].Inn := Copy(sPart, Pos('Inn: ', sPart) + 5, MaxInt)
else
If Pos('Shrine to ', sPart) > 0 then
SeparatePart(Copy(sPart, Pos('Shrine to ', sPart) + 10, MaxInt), Villages[x].Gods)
else
If Pos('Shrines to ', sPart) > 0 then // different god part
SeparatePart(Copy(sPart, Pos('Shrines to ', sPart) + 11, MaxInt), Villages[x].Gods)
else
If Pos('Taverns: ', sPart) > 0 then
SeparatePart(Copy(sPart, Pos('Taverns: ', sPart) + 9, MaxInt), Villages[x].Taverns)
else
If Pos('Trade: ', sPart) > 0 then
SeparatePart(Copy(sPart, Pos('Trade: ', sPart) + 7, MaxInt), Villages[x].Trade)
else begin
If Pos('farme', sPart) > 0 then
Villages[x].Farmers := StrToInt(Trim(Copy(sPart, Pos('farme', sPart) - 3, 3)));
If Pos('artis', sPart) > 0 then
Villages[x].Artisans := StrToInt(Trim(Copy(sPart, Pos('artis', sPart) - 3, 3)));
If Pos('labor', sPart) > 0 then
Villages[x].Laborers := StrToInt(Trim(Copy(sPart, Pos('labor', sPart) - 3, 3)));
If Pos('paupe', sPart) > 0 then
Villages[x].Paupers := StrToInt(Trim(Copy(sPart, Pos('paupe', sPart) - 3, 3)));
end;
GetNextPart(sTempLine, sPart);
end;
end;
end; {proc Convert}
begin
{GetVillageLines;}
Fileline[1]:='Aike - Pop 75 (16 fams). Gov: Squire. Shrine to Deneir. Inn: The Blue Chimera. 4 farmers, 2 artisans, 8 laborers, 2 paupers. Trade: beef.';
Fileline[2]:='Aire View - Pop 312 (63 fams). Gov: Priest. Shrines to Ulutiu and Bhaal. Inn: The Lost Horn. Taverns: The Drunken Ogre, The Golden Arms. 16 farmers, 9 artisans, 32 laborers, 6 paupers. Trade: barley, corn.';
Fileline[3]:='Barwick-in-Elmet - Pop 369 (77 fams). Gov: Magistrate. Shrines to Iyachtu Xvim and Gwaeron Windstrom. Inn: The Crooked Orc. Taverns: The Blue Priest, The Dirty Serpent. 19 farmers, 12 artisans, 39 laborers, 8 paupers. Trade: corn, turnips.';
Fileline[4]:='Scorborough - Pop 341 (72 fams). Gov: Constable. Shrines to Nobanion and Ibrandul. Inn: The Wild Tankard. Taverns: The Wild Minstrel, The Wild Chimera. 18 farmers, 11 artisans, 36 laborers, 7 paupers. Trade: potatoes, pears.';
Recds:=4;
Convert;
// not part of converting
For iCnt := 1 to Recds do // This loop is to display what I've done so far.
Begin
WriteLn('Village Name Fileline ',iCnt,': ',Villages[iCnt].Name,
' Population: ',Villages[iCnt].Population,
' Government: ',Villages[iCnt].Government);
WriteLn( ' Families: ',Villages[iCnt].Families,
' Farmers: ',Villages[iCnt].Farmers,
' Artisans: ',Villages[iCnt].Artisans,
' Laborers: ',Villages[iCnt].Laborers,
' Paupers: ',Villages[iCnt].Paupers);
WriteLn(' Inn: ', Villages[iCnt].Inn);
Write( ' Gods: ');
For iCnt2 := 1 to 3 do Write('''' + Villages[iCnt].Gods[iCnt2] + ''' ');
WriteLn;
Write( ' Taverns: ');
For iCnt2 := 1 to 3 do Write('''' + Villages[iCnt].Taverns[iCnt2] + ''' ');
WriteLn;
Write( ' Trade: ');
For iCnt2 := 1 to 3 do Write('''' + Villages[iCnt].Trade[iCnt2] + ''' ');
WriteLn;
WriteLn;
end; {For iCnt}
ReadLn;
end. {Program Villages}