program CevoMapCheck;

{***********************************************************

Project:    C-evo External Map Generator
Copyright:  2021-2026 P Blackman
License:    GPLv3+

Program to check map file validity and
output some statistcs

***********************************************************}

{$linklib c}

uses CevoMapFile, CevoMap, MapTiles;

var
    MapFile : tMapFile;
    Map     : tMap;
    FileNam : string;


function GetMapFileName : Boolean;
begin
    if ParamCount >= 1 then
    begin
        FileNam := ParamStr(1);
        result  := True;
    end
    else
    begin
        FileNam := '';
        result  := False;
    end;
end;

procedure ShowStartPos (W,H : Integer);
var DeadLand : Boolean;
begin
    Writeln (MapFile.MapIndex(W,H)-1:5, '  ', Map.StartScore (W,H,Deadland));
end;

procedure CheckMapBody;
var StartPositions, W, H,
    DeadLands_count,
    Cobalt_count,
    Uranium_count,
    Mercury_count : Integer;

begin
    StartPositions := 0;
    DeadLands_count  := 0;
    Cobalt_count     := 0;
    Uranium_count    := 0;
    Mercury_count    := 0;

    with MapFile do
    begin
        Writeln ('Start-Positions');
        Writeln ('Locn  Score');
        Writeln ('----- ----');
        for W := 1 to Width do
            for H := 1 to Height do
            begin
                If fBody[MapIndex(W,H)].StartPos and $60 in [$20, $40] then
                begin
                    inc (StartPositions);
                    ShowStartPos (W,H);
                end;

                case fBody[MapIndex(W,H)].Special of
                      NoSpecial : {Nothing here};
                      DeadLands : inc (DeadLands_count);
                      Cobalt    : inc (Cobalt_count);
                      Uranium   : inc (Uranium_count);
                      Mercury   : inc (Mercury_count);
                otherwise
                    writeln ('Invalid special ',Ord(fBody[MapIndex(W,H)].Special), ' at ', MapIndex(W,H));
                end;
            end;

        Writeln ('----- ----');
        Writeln ('Total  ',StartPositions);
        Writeln;
        Writeln ('Cobalt    ', Cobalt_count);
        Writeln ('Uranium   ', Uranium_count);
        Writeln ('Mercury   ', Mercury_count);
        Writeln ('DeadLands ', DeadLands_count);
    end;
end;

procedure ShowTerrain;

var W,H,MapSize,EarlyBonusRes, LateBonusRes,
    OceanTiles,CoastTiles,GrassTiles,DesertTiles,PrairieTiles,TundraTiles,
    ArcticTiles,SwampTiles,ForestTiles,HillsTiles,MountainTiles,RiverTiles : Integer;
    Bonus : tResource;
    BonusRes : Double;

begin
    OceanTiles      :=0;
    CoastTiles      :=0;
    GrassTiles      :=0;
    DesertTiles     :=0;
    PrairieTiles    :=0;
    TundraTiles     :=0;
    ArcticTiles     :=0;
    SwampTiles      :=0;
    ForestTiles     :=0;
    HillsTiles      :=0;
    MountainTiles   :=0;
    RiverTiles      :=0;
    EarlyBonusRes   :=0;
    LateBonusRes    :=0;
    MapSize         := Map.Width * Map.Height;

    with Map do
    for W := 1 to Width do
      for H := 1 to Height do
      begin
        case GetTerrain (W, H) of
            Ocean   : inc (OceanTiles);
            Coast   : inc (CoastTiles);
            Grass   : inc (GrassTiles);
            Desert  : inc (DesertTiles);
            Prairie : inc (PrairieTiles);
            Tundra  : inc (TundraTiles);
            Arctic  : inc (ArcticTiles);
            Swamp   : inc (SwampTiles);
            Forest  : inc (ForestTiles);
            Hills   : inc (HillsTiles);
            Mountain : inc (MountainTiles);
            otherwise
                Writeln ('Invalid Terrain Tile ',W, ' ',H, ' ',Ord(GetTerrain (W, H)));
        end;

        if Tiles[W,H].River then
            inc (RiverTiles);

        Bonus := GetBonus (W, H);

        If (Bonus = EarlyBonus) and (GetTerrain (W, H) <> Grass) then
            inc (EarlyBonusRes);
        If Bonus = LateBonus then
            inc (LateBonusRes);
      end;

   if MapSize = OceanTiles then
        BonusRes := 0.0
    else
        BonusRes := (EarlyBonusRes+LateBonusRes) * (MapSize / (MapSize-OceanTiles));

    Writeln ('Ocean%    ', Round(100*OceanTiles   /MapSize):2);
    Writeln ('Coast%    ', Round(100*CoastTiles   /MapSize):2);
    Writeln ('Grass%    ', Round(100*GrassTiles   /MapSize):2);
    Writeln ('Desert%   ', Round(100*DesertTiles  /MapSize):2);
    Writeln ('Prairie%  ', Round(100*PrairieTiles /MapSize):2);
    Writeln ('Tundra%   ', Round(100*TundraTiles  /MapSize):2);
    Writeln ('Arctic%   ', Round(100*ArcticTiles  /MapSize):2);
    Writeln ('Swamp%    ', Round(100*SwampTiles   /MapSize):2);
    Writeln ('Forest%   ', Round(100*ForestTiles  /MapSize):2);
    Writeln ('Hills%    ', Round(100*HillsTiles   /MapSize):2);
    Writeln ('Mountain% ', Round(100*MountainTiles/MapSize):2);
    Writeln;
    Writeln ('Rivers%   ', Round(100*RiverTiles   /MapSize):2);
    Writeln ('Resource% ', (100* BonusRes / MapSize):4:1);
end;

procedure Report;
begin
    with MapFile.fHeader do
    begin
        Writeln;
        Writeln (FileNam);
        Writeln ('Size: ',LX, 'x', LY, LX*LY:6);
        Writeln;
        Map := tMap.Create (LX, LY, 0, 0);
        MapFile.LoadMapData (Map);
        CheckMapBody;
        Writeln;
        ShowTerrain;
        Writeln;
        Map.Free;
    end;
end;

begin
    MapFile := tMapFile.Create;
    FileNam := '';

    if GetMapFileName then
    begin
        if MapFile.OpenMFile (FileNam) then
            if MapFile.LoadFromFile then
                Report
            else
                Writeln ('Failed to load file: ', FileNam);
    end
    else
        Writeln ('cevomapcheck requires a filename as parameter');

     MapFile.Free;
end.
