unit Map;

interface

uses
  Classes, SysUtils;

type

  { TMap }

  TMap = class
  private
    FSize: TPoint;
    function GetMapSize: Integer;
    procedure SetSize(AValue: TPoint);
  public
    MaxTurn: Integer;
    FormatId: Integer;
    Tiles: array of Cardinal;
    procedure LoadFromFile(FileName: string);
    procedure SaveToFile(FileName: string);
    constructor Create;
    property MapSize: Integer read GetMapSize;
    property Size: TPoint read FSize write SetSize;
  end;


implementation

uses
  Protocol;

const
  FileId = 'cEvoMap'#0;

procedure TMap.SaveToFile(FileName: string);
var
  MapFile: TFileStream;
begin
  MapFile := TFileStream.Create(FileName, fmCreate or fmShareExclusive);
  try
    MapFile.Position := 0;
    MapFile.Write(FileId[1], 8);
    MapFile.Write(FormatId, 4);
    MapFile.Write(MaxTurn, 4);
    MapFile.Write(Size.X, 4);
    MapFile.Write(Size.Y, 4);
    MapFile.Write(Tiles[0], MapSize * 4);
  finally
    FreeAndNil(MapFile);
  end;
end;

constructor TMap.Create;
begin
  FormatId := 0;
end;

function TMap.GetMapSize: Integer;
begin
  Result := Size.X * Size.Y;
end;

procedure TMap.SetSize(AValue: TPoint);
begin
  if FSize = AValue then Exit;
  FSize := AValue;
  SetLength(Tiles, MapSize);
end;

procedure TMap.LoadFromFile(FileName: string);
var
  Loc1: Integer;
  MapFile: TFileStream;
  ReadFileId: string;
  ReadFormatId: Integer;
  Width: Integer;
  Height: Integer;
begin
  ReadFileId := '';
  ReadFormatId := 0;
  Width := 0;
  Height := 0;
  if not FileExists(FileName) then Exit;
  MapFile := TFileStream.Create(FileName, fmOpenRead or fmShareExclusive);
  try
    MapFile.Position := 0;
    SetLength(ReadFileId, 8);
    MapFile.Read(ReadFileId[1], 8);
    if ReadFileId <> FileId then
      raise Exception.Create('Incorrect map file id. Expected ''' + Trim(FileId) +
        ''' but ''' + Trim(ReadFileId) + ''' read.');
    MapFile.Read(ReadFormatId, 4);
    if ReadFormatId = 0 then begin
      MapFile.Read(MaxTurn, 4);
      MapFile.Read(Width, 4);
      MapFile.Read(Height, 4);
      Height := Height and not 1;
      if Width > lxmax then
        Width := lxmax;
      if Height > lymax then
        Height := lymax;
      Size := Point(Width, Height);
      MapFile.Read(Tiles[0], MapSize * 4);
      for Loc1 := 0 to MapSize - 1 do begin
        Tiles[Loc1] := Tiles[Loc1] and
          ($7F01FFFF or fPrefStartPos or fStartPos) or ($F shl 27);
        if Tiles[Loc1] and (fTerrain or fSpecial) = fSwamp or fSpecial2 then
          Tiles[Loc1] := Tiles[Loc1] and not (fTerrain or fSpecial) or
            (fSwamp or fSpecial1);
        if (Tiles[Loc1] and fDeadLands <> 0) and
          (Tiles[Loc1] and fTerrain <> fArctic) then
          Tiles[Loc1] := Tiles[Loc1] and not (fTerrain or fSpecial)
            or fDesert;
      end;
    end else raise Exception.Create('Unsupported map format id ' + IntToStr(ReadFormatId) + '.');
  finally
    FreeAndNil(MapFile);
  end;
end;

end.

