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

Project:    C-evo External Map Generator
Copyright:  1999-2024 P Blackman
License:    GPLv3+

Routines for allocation of terrain resources

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


// Function taken from Protocol.pas in C-evo source
// Do NOT change logic unless Protocol.pas changes
function SpecialTile(Loc, lx: Integer; TerrType: tTerrain): Integer;
var
    x, y, qx, qy, a: Integer;
begin
    if TerrType = Ocean then
        Result := 0
    else
    begin
        y := Loc DIV lx;
        x := Loc - y * lx;
        if TerrType = Grass then
        begin
            if Odd((lymax + x - y SHR 1) SHR 1 + x + (y + 1) SHR 1) then
                Result := 1  // formula for plains
            else
                Result := 0
        end
        else
        // formula for special resources
        begin
            a  := 4 * x - y + 9980; // 9980 seems to be an arbirary multiple of 80
            qx := a DIV 10;
            if (qx * 10 = a) AND (qx AND 3 <> 0) then
            begin
                qy := (y + x) DIV 5;
                if qy AND 3 <> qx SHR 2 AND 1 * 2 then
                    if (TerrType = Arctic) OR (TerrType = Swamp) then
                        Result := 1
                    else if TerrType = Coast then
                    begin
                        if (qx + qy) AND 1 = 0 then
                            if qx AND 3 = 2 then
                                Result := 2
                            else
                                Result := 1
                        else
                            Result := 0;
                    end
                    else
                        Result := (qx + qy) AND 1 + 1
                else
                    Result     := 0;
            end
            else
                Result := 0;
        end;
    end;
end;


// ---------------- Resource Allocation ---------------------

function tMap.GetBonus(W, H: Integer): tResource;
begin
    Result := Tiles[W, H].Resource;
    Assert((Result >= Nothing) AND (Result <= LateBonus));
end;

function tMap.GetSpecial(W, H: Integer): tSpecial;
begin
    Result := Tiles[W, H].Special;
end;

procedure tMap.SetBonus(W, H: Integer; R: tResource);
begin
	if (R >= Nothing) AND (R <= LateBonus) then
		Tiles[W, H].Resource := R;
end;

procedure tMap.SetSpecial(W, H: Integer; S: tSpecial);
begin
    Tiles[W, H].Special := S;
end;


procedure tMap.SetResource (W,H,Q : Integer);
var T : tTerrain;
    R, Loc : integer;
begin
    Tiles [W,H].Resource := Nothing;
    T := getTerrain (W,H);

    if (Q = -1) or (T in [Ocean, Grass]) then
    // use in game algorithm
    begin
        Loc := W-1 + Width * (H-1);

        R := SpecialTile(Loc, Width, T);
        Tiles[W, H].Resource := tResource(R);
    end
    else
    // use Resource Level (Q) as percentage
    if random (100) < Q then
    begin
        R := 1 + Random (2);  // R either 1 or 2

        if T in [Arctic, Swamp] then
        begin
            // No 2nd (late) resource
            if R = 1 then
                Tiles [W,H].Resource := EarlyBonus;
        end
        else
            // All other terrain types
            Tiles [W,H].Resource := tResource(R);
    end;
end;


procedure tMap.AllocateResources (Q: Integer);
var W, H: Integer;
begin
    for W := 1 to Width do
        for H := 1 to Height do
            SetResource(W, H, Q);
end;
