What I proposed expressed as code. Obviously, data types and data structures aren't like that, but it should be possible to understand what info the code make use of. For those who wonder what weird language the code is written in: it's Ada.
Void_Cost : constant Float := 1.0 / 320.0;
Global_Max_Distance : constant Integer := 20;
function Shall_Mature (Tree : in Tree_Pointer) return Boolean is
Sum : Float := 0.0;
Dist : Integer;
begin
for I in -Global_Max_Distance .. Global_Max_Distance loop
for K in -Global_Max_Distance .. Global_Max_Distance loop -- I = 0, K = 0 is the sapling itself, but evaluating it doesn't matter since it adds 0.0.
if abs (I) > abs (K) then
Dist := abs (I);
else
Dist := abs (K);
end if;
if Tree.X + I in 1 .. Embark.Max_X and then -- Assuming embark is in 1 .. X_Max, 1 .. Y_Max. It's probably 0 .. *_Max - 1 when C(++) is used.
Tree.Y + K in 1 .. Embark.Max_Y then
if Embark.Tile (Tree.X + I, Tree.Y + K, Tree.Z).Biome = Ocean or else
Embark.Tile (Tree.X + I, Tree.Y + K, Tree.Z).Biome = Air or else -- And so on for all non tree bearing biomes. Probably done differently in practice.
Embark.Tile (Tree.X + I, Tree.Y + K, Tree.Z).Biome = Rock then
Sum = Sum + Void_Cost / Float (Dist);
else
if Embark.Tile (Tree.X + I, Tree.Y + K, Tree.Z).Biome.Tree_Maturation_Distance <= Dist and then then -- Otherwise too far away to matter
Embark.Tile (Tree.X + I, Tree.Y + K, Tree.Z).Tree_Present then
Sum := Sum + 1.0 / Float (Dist) / Embark.Tile (Tree.X + I, Tree.Y + K, Tree.Z).Biome.Tree_Maturation_Density_Acceptance;
end if;
end if;
else
Sum := Sum + Void_Cost / Float (Dist); -- Tiles outside the embark still apply the forest-less load.
end if;
end loop;
end loop;
return Random_Number >= Sum;
end Shall_Mature;