local trees = {"t02", "t06", "t10", "t11", "t13", "t14", "t15"} local map = {} -- mp0 is top-left -- mp1 is down-left -- mp2 is down-right -- mp3 is top-right local mpspawns = {} -- idk why it didn't work like {["mp0"] = {10, 10}, ["mp1"] = {10, 118}, ["mp2"] = {118, 118}, ["mp3"] = {118, 10}} mpspawns["mp0"] = {10, 10} mpspawns["mp1"] = {10, 118} mpspawns["mp2"] = {118, 118} mpspawns["mp3"] = {118, 10} local w = 128 local h = 128 local Neutral = Player.GetPlayer("Neutral") -- Based on Murto's experiment with forest generation -- Main goal is to make it playable (and practice programming) function ParseTile(x, y, offset) local areaWeight = 0 for tileX = x - offset, x + offset do for tileY = y - offset, y + offset do if (tileX > 0 and tileY > 0) and (tileX < w and tileY < h) then if((tileX ~= x) or (tileY ~= y))then if map[tileX][tileY] ~= 2 then areaWeight = areaWeight + map[tileX][tileY] end end end end end return areaWeight end function ParseTileGold(x, y, offset) local areaWeight = 0 for tileX = x - offset, x + offset do for tileY = y - offset, y + offset do if (tileX > 0 and tileY > 0) and (tileX < w and tileY < h) then if((tileX ~= x) or (tileY ~= y))then areaWeight = areaWeight + map[tileX][tileY] end end end end return areaWeight end function FillCorners() Media.Debug("Filling corners with trees.") for x=1,w do for y=1,h do -- I am more than sure one can make this shorter, but i made it to be sure in everything. if ((h >= y) and (y >= 1)) and x == 1 then map[x][y] = 1 elseif y == 1 and ((w >= x) and (x >= 1)) then map[x][y] = 1 elseif x == w and ((h >= y) and (y >= 1)) then map[x][y] = 1 elseif y == h and ((w >= x) and (x >= 1)) then map[x][y] = 1 end end end end function ClearArea(x, y, offset) for tileX = x - offset, x + offset do for tileY = y - offset, y + offset do if map[tileX][tileY] == 1 then map[tileX][tileY] = 0 end end end end function ClearPlayerSpawns() Media.Debug("Clearing spawns.") ClearArea(mpspawns["mp0"][1], mpspawns["mp0"][2], 4) ClearArea(mpspawns["mp0"][1], mpspawns["mp0"][2], 4) ClearArea(mpspawns["mp1"][1], mpspawns["mp1"][2], 4) ClearArea(mpspawns["mp1"][1], mpspawns["mp1"][2], 4) ClearArea(mpspawns["mp2"][1], mpspawns["mp2"][2], 4) ClearArea(mpspawns["mp2"][1], mpspawns["mp2"][2], 4) ClearArea(mpspawns["mp3"][1], mpspawns["mp3"][2], 4) ClearArea(mpspawns["mp3"][1], mpspawns["mp3"][2], 4) end function Blanking() Media.Debug("Applying blanking.") for x= (w / 2), (w / 2 + 1) do for y=5, h-5 do map[x][y] = 0 end end -- Magic numbers... Those magic numbers are coordinates of mpspawn actors found in map.yaml for x = mpspawns["mp0"][1], mpspawns["mp0"][1] + 1 do -- This 11 is here so we make 2 tiles blank space for y = 5, h - 5 do map[x][y] = 0 end end for x = mpspawns["mp2"][1], mpspawns["mp2"][1] + 1 do for y = 5, h - 5 do map[x][y] = 0 end end -- Here comes horizontal blanking so we can connect all the spawns together for x = 10, w - 10 do -- Again, spawn cordinates for y = mpspawns["mp0"][2], mpspawns["mp0"][2] + 1 do -- And again, coordinates, coordinates+1 map[x][y] = 0 end end for x = 10, w - 10 do -- Again, spawn cordinates for y = mpspawns["mp1"][2], mpspawns["mp1"][2] + 1 do -- And again, coordinates, coordinates+1 map[x][y] = 0 end end end function SmoothMap() -- Actually, this isn't how one should do it. -- Right way to do this is to create a new table with map -- And fill it based on data from old map, then assing new map to old one -- But because this script has limited quota, one can't afford a new table here, -- So we are operating on existing map, while having mix of old and new data. Bad thing! Media.Debug("Smoothing map.") for x=2, w-2 do for y=2, h-2 do local areaWeight = ParseTile(x, y, 1) if(areaWeight >= 4 and map[x][y] == 1) then map[x][y] = 1 elseif(areaWeight >= 5 and map[x][y] == 0) then map[x][y] = 1 else map[x][y] = 0 end end end end function CreateVisual(x,y) if map[x][y] == 1 then local actor = Actor.Create(Utils.Random(trees), true, { Owner = Neutral, Location = CPos.New(x, y) }) elseif map[x][y] == 2 then local actor = Actor.Create(Utils.Random({"mine", "gmine"}), true, { Owner = Neutral, Location = CPos.New(x, y) }) end end function GoldInArea(x, y, offset, max) local goldInArea = 0 for tileX = x - offset, x + offset do for tileY = y - offset, y + offset do if (tileX > 0 and tileY > 0) and (tileX < w and tileY < h) then if((tileX ~= x) or (tileY ~= y))then if map[tileX][tileY] == 2 then goldInArea = goldInArea + 1 end if goldInArea > max then return false end end end end end return true end function PlaceTreasure() Media.Debug("Placing gold.") for x = 20, w-20 do for y = 20, h-20 do if map[x][y] == 0 then local goldInArea = GoldInArea(x, y, 10, 1) if goldInArea then local weight = ParseTile(x, y, 1) local bigWeight = ParseTile(x, y, 7) if weight >= 4 then map[x][y] = 2 elseif bigWeight == 0 then if ParseTileGold(x, y, 4) == 0 then map[x][y] = 2 end end end end end end end function RenderMap() Media.Debug("Rendering.") for x=1, w do for y=1, h do if map[x][y] == 1 or map[x][y] == 2 then CreateVisual(x,y) end end end end function WorldGenerationSequence() Media.Debug("Randomly filling map with treees!") for x=1,w do map[x] = {} for y=1,h do map[x][y] = Utils.RandomInteger(0, 2) end end Media.Debug("Starting world generation sequence!") ClearPlayerSpawns() Blanking() SmoothMap() SmoothMap() FillCorners() PlaceTreasure() RenderMap() end WorldLoaded = function() Trigger.AfterDelay(0.1, WorldGenerationSequence) end