SHARE
TWEET

dual pass cave generation algorithm

a guest Apr 26th, 2017 55 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local CHANCE_TO_START_ALIVE = 480
  2. local BIRTH_LIMIT = 5
  3. local DEATH_LIMIT = 5
  4. -- in phase 2 there's more death than birth in order to widen paths
  5. local BIRTH_LIMIT_PHASE2 = 5
  6. local DEATH_LIMIT_PHASE2 = 6
  7. local STEPS = 3 -- per phase
  8.  
  9. local distance = 64
  10. local pointSize = 11
  11.  
  12. local lastx
  13. local lasty
  14. -- function for updating last possible x and y indexes
  15. function updateLastXY()
  16.   -- +1 to make sure we touch the walls
  17.   lastx = math.floor(4096/distance) + 1
  18.   lasty = math.floor(2048/distance) + 1
  19. end
  20. -- initialize
  21. updateLastXY()
  22.  
  23.  
  24. function generateCave()
  25.  
  26.   local world = {}
  27.  
  28.   -- PHASE 1
  29.  
  30.   -- generate low resolution world
  31.   initializeWorld(world)
  32.  
  33.   for i=1, STEPS do
  34.     world = simulationStep(world)
  35.   end
  36.  
  37.   -- PHASE 2
  38.  
  39.   -- okay, we got a rough cave shape now
  40.   -- double its resolution and simulate again to refine shape
  41.   world = doubleWorldResolution(world)
  42.  
  43.   DEATH_LIMIT = DEATH_LIMIT_PHASE2
  44.   BIRTH_LIMIT = BIRTH_LIMIT_PHASE2
  45.  
  46.   for i=1, STEPS do
  47.     world = simulationStep(world)
  48.   end
  49.  
  50.   -- DRAWING
  51.  
  52.   local realx = 0
  53.   for x=1, lastx do
  54.  
  55.     local realy = 0
  56.     for y=1, lasty do
  57.  
  58.       if world[x][y] then
  59.         AddPoint(realx, realy, pointSize)
  60.       end
  61.  
  62.       realy = realy + distance
  63.     end
  64.     realx = realx + distance
  65.   end
  66.  
  67.   FlushPoints()
  68. end
  69.  
  70. -- doubles the world resolution in both x and y direction
  71. -- causing every cell/space become 4 cells/spaces each
  72. function doubleWorldResolution(world)
  73.  
  74.   -- update distance to reflect the change
  75.   distance = math.floor(distance / 2)
  76.   updateLastXY()
  77.  
  78.   local world2 = {}
  79.  
  80.   -- generate 2 lines at once, because they are identical
  81.   for x=1, lastx, 2 do
  82.     local oddcol = {}
  83.     local evencol = {}
  84.  
  85.     -- generate 2 cells per column at once, because they are identical
  86.     for y=1, lasty, 2 do
  87.       local wx = math.floor(x/2)+1
  88.       local wy = math.floor(y/2)+1
  89.       local cell = world[wx][wy]
  90.       -- add 2 cells in both columns
  91.       table.insert(oddcol, cell)
  92.       table.insert(oddcol, cell)
  93.       table.insert(evencol, cell)
  94.       table.insert(evencol, cell)
  95.     end
  96.  
  97.     -- add the two columns
  98.     table.insert(world2, oddcol)
  99.     table.insert(world2, evencol)
  100.   end
  101.  
  102.   return world2
  103. end
  104.  
  105. function initializeWorld(world)
  106.   for x=1, lastx do
  107.     table.insert(world, {})
  108.     local borderx = (x == 1) or (x == lastx)
  109.  
  110.     for y=1, lasty do
  111.       local border = borderx or ((y == 1) or (y == lasty))
  112.       if border or GetRandom(1000) < CHANCE_TO_START_ALIVE then
  113.         table.insert(world[x], true)
  114.       else
  115.         table.insert(world[x], false)
  116.       end
  117.     end
  118.   end
  119. end
  120.  
  121. function simulationStep(world)
  122.   world2 = {}
  123.  
  124.   for x=1, lastx do
  125.     table.insert(world2, {})
  126.  
  127.     for y=1, lasty do
  128.       local count = countNeigbours(world, x, y)
  129.  
  130.       if world[x][y] then
  131.         if count < DEATH_LIMIT then
  132.           table.insert(world2[x], false)
  133.         else
  134.           table.insert(world2[x], true)
  135.         end
  136.       else
  137.         if count > BIRTH_LIMIT then
  138.           table.insert(world2[x], true)
  139.         else
  140.           table.insert(world2[x], false)
  141.         end
  142.       end
  143.     end
  144.   end
  145.  
  146.   return world2
  147. end
  148.  
  149. function countNeigbours(world, x, y)
  150.   count = 0
  151.  
  152.   for dx=-1, 1 do
  153.     for dy=-1, 1 do
  154.       local x2 = x+dx
  155.       local y2 = y+dy
  156.  
  157.       if x2 == 0 or x2 > lastx or y2 == 0 or y2 > lasty or world[x2][y2] then
  158.         count = count + 1
  159.       end
  160.     end
  161.   end
  162.  
  163.   return count
  164. end
  165.  
  166. function onGameInit()
  167.     MapGen = mgDrawn
  168.     TemplateFilter = 0
  169.     generateCave()
  170. end
  171.  
  172. function onPreviewInit()
  173.     onGameInit()
  174. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top