Guest User

dual pass cave generation algorithm

a guest
Apr 26th, 2017
69
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