Kaikaku

ccPyramidRun_builder.lua_v1.00

May 15th, 2015 (edited)
721
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 72.13 KB | None | 0 0
  1. --{program="builder",version="1.00",date="2015-05-15"}
  2. ---------------------------------------
  3. -- builder             by Kaikaku
  4. -- 2015-05-15, v1.00   initial version
  5.    local cProgam   ="builder"
  6.    local cVersion  ="v1.00"
  7. ---------------------------------------
  8.  
  9. ---------------------------------------
  10. ---- DESCRIPTION ----------------------
  11. ---------------------------------------
  12. -- This program sets up the labyrinths in the pyramids
  13. -- It's called by other computers
  14.  
  15. ---------------------------------------
  16. ---- PARAMETERS -----------------------
  17. ---------------------------------------
  18. -- debugging and testing
  19. local blnDebug=true --false --        -- displays debug messages
  20. local intDebugLevel=1--0              -- will do some filtering stuff w/ this
  21.                                       -- 0 = only temp things are set to 0
  22.                                       -- 1 = main steps
  23.                                       -- 2 = basic info for main steps
  24.                                       -- 3 = detailed function calls
  25.                                       -- 4 = detailed that are probably not used any more
  26.                                       -- 5 = execute also some askForText stops
  27. local strDebugPrompt="D:"             -- debug messages start with this
  28. local intDebugCounter=0               -- to split screens
  29. local intDebugStopCounter=0           -- how often stopped
  30. local intDebugStopAt=9999 --9999 --   -- when to stop. If very high then no stop at all. more than 18 will hide info for sure
  31. local blnJustClear= false --true --   -- clears the field without putting new stuff
  32. local blnAllRndInteriorBlocks = false --true -- if true, all options will be used in each room
  33. local blnAllRndInteriorBases = false  --true -- if true, all base options will be used in each room
  34. local blnAllRndSubinteriors = false -- true -- if true, all subinteriors will be used in each room
  35. local blnAllSummons = false -- true         -- true -- if true, all summons will be used in each room
  36. local blnNoGlassRoof=false --true --  --if true, then open roof
  37. local blnClearBeforeBuild=true --false--
  38.  
  39. -- room parameters
  40. local cRoomDepth =11         -- direction x
  41. local cRoomHeight=5          --           y
  42. local cRoomWidth =cRoomDepth --           z
  43.  
  44. local cRoomMaterial           = "minecraft:sandstone" --"minecraft:bedrock"
  45. local cRoomMaterialDmg        = 0
  46. local cRoomMaterialCeiling    = "chisel:glass" --"OpenBlocks:tank" --"ExtraUtilities:decorativeBlock2"
  47. local cRoomMaterialCeilingDmg = 6
  48.  
  49. local cTrapProbability=0.25 -- how probable it is to trap any y=-1/0/1 chest
  50.  
  51. -- default labyrinth values
  52. --   some (all?) of the default values may be overwritten if #tArgs==6
  53. local xHome=0
  54. local yHome=0
  55. local zHome=0
  56. xHome, yHome, zHome = commands.getBlockPosition() -- memo: not included in task limit!
  57.  
  58. local cOffsetX   =4          
  59. local cOffsetY   =4-22
  60. local cOffsetZ   =4-20
  61.  
  62. local cRoomsGridX=3 -- 5 --        -- number of rooms in x direction
  63. local cRoomsGridZ=3 -- 5 --        --                    z direction
  64.  
  65. local intLabLevel=2 -- 1 -- default labyrinth difficulty level
  66.  
  67. -- material ids
  68. local cMatId_RoomIndicator = "266" --=minecraft:gold_ingot
  69. local cMatId_GoldIngot="266"
  70. local cMatId_GoldNugget="371"
  71. local cMatId_GoldOre="14"
  72. local cMatId_FlintAndSteel="259"
  73. local cMatId_WoodenSword="268"
  74. local cMatId_DiscCat="2257" -- not sure about this ID! Depending on mod pack?
  75. local cMatId_DiscFar="2260" -- not sure about this ID! Depending on mod pack?
  76.  
  77. ---------------------------------------
  78. ---- tArgs ----------------------------
  79. ---------------------------------------
  80.  
  81. -- (disabled) builder "del"
  82. -- (disabled) builder xRoom zRoom
  83. -- (disabled) builder xRoom zRoom "del"
  84. -- (disabled) builder x y z xRoom zRoom level
  85. -- builder x y z xRoom zRoom "del" (clear included)
  86.  
  87. local tArgs = {...}
  88. local tmpArg=0  
  89. local blntArgsOk=false
  90. --[[ used for developing and testing
  91. if #tArgs == 1 then -- no error check
  92.   if tArgs[1]=="delete" or tArgs[1]=="del" then
  93.     blntArgsOk=true
  94.     blnJustClear=true
  95.   end  
  96. end
  97. if #tArgs == 2 or #tArgs == 3 then -- no error check
  98.   cRoomsGridX=math.floor(tonumber(tArgs[1]))
  99.   cRoomsGridZ=math.floor(tonumber(tArgs[2]))
  100.   if cRoomsGridX<2 then cRoomsGridX=2 end
  101.   if cRoomsGridX>5 then cRoomsGridX=5 end
  102.   if cRoomsGridZ<2 then cRoomsGridZ=2 end
  103.   if cRoomsGridZ>5 then cRoomsGridZ=5 end
  104.     blntArgsOk=true
  105. end
  106. if #tArgs == 3 then -- no error check
  107.   if tArgs[3]=="delete" or tArgs[3]=="del" then
  108.     blntArgsOk=true
  109.     blnJustClear=true
  110.   end  
  111. end
  112. ]]--
  113. if #tArgs >= 6 then -- no error check
  114.   xHome=tonumber(tArgs[1]) cOffsetX=0
  115.   yHome=tonumber(tArgs[2]) cOffsetY=0
  116.   zHome=tonumber(tArgs[3]) cOffsetZ=0
  117.   cRoomsGridX=math.floor(tonumber(tArgs[4]))
  118.   cRoomsGridZ=math.floor(tonumber(tArgs[5]))
  119.   if cRoomsGridX<2 then cRoomsGridX=2 end
  120.   if cRoomsGridX>5 then cRoomsGridX=5 end
  121.   if cRoomsGridZ<2 then cRoomsGridZ=2 end
  122.   if cRoomsGridZ>5 then cRoomsGridZ=5 end
  123.   tmpArg=tonumber(tArgs[6])
  124.   if tmpArg~=nil then
  125.     intLabLevel=tmpArg
  126.     if intLabLevel>5 then intLabLevel=5 end
  127.     if intLabLevel<1 then intLabLevel=1 end
  128.     blntArgsOk=true
  129.   elseif tArgs[6]=="delete" or tArgs[6]=="del" then
  130.     -- del?
  131.     blntArgsOk=true
  132.     blnJustClear=true  
  133.   end
  134. else
  135.   commands.say("Ups, sorry! Error calling pyramid builder...")
  136. end
  137.  
  138. local finalCommand=""
  139. if #tArgs >= 7 then -- final command to finish execution?
  140.   for i=7,#tArgs do
  141.     finalCommand=finalCommand..tArgs[i].." "
  142.   end
  143. end
  144.  
  145. if not blntArgsOk then
  146.   debugPrint(0,"ERROR: Something wrong with provided parameters!")
  147.   return
  148. end
  149.  
  150. ---------------------------------------
  151. ---- VARIABLES ------------------------
  152. ---------------------------------------
  153. local maxCommands=250  -- to overcome task limit --250
  154. local curCommands=0    -- to overcome task limit
  155. local curCounter=0
  156. local curCounterComplete=0
  157.  
  158. local exitRoomZ=0 -- z coordinate of exit in doors[]
  159. local entrRoomZ=0 -- z coordinate of entrance in doors[]
  160. local countInteriors={}
  161.  
  162. local goldDistribution={} -- used to randomly distribute gold ingots and nuggets
  163.                           -- {"id","count"}
  164.                          
  165. -- monitor thingies              
  166. local mon   = peripheral.wrap("right")
  167. local monLevel=0 --3x3,3x4,4x4,4x5,5x5
  168.   if cRoomsGridX==3 then
  169.     monLevel=1
  170.   elseif cRoomsGridZ==5 then
  171.     monLevel=5
  172.   elseif cRoomsGridX==5 then
  173.     monLevel=4
  174.   elseif cRoomsGridZ==4 then
  175.     monLevel=3
  176.   elseif cRoomsGridZ==3 then
  177.     monLevel=2
  178.   else
  179.     print("Error: monitor thingie")
  180.   end
  181.  
  182. local monCount={18500,25500,34000,43500,53500}
  183. term.redirect(mon) term.clear() term.setCursorPos(1,1) print("       Pyramid") print("  ",monLevel,"/5")term.redirect(term.native())
  184.  
  185. local function updateMon()
  186.  
  187.   term.redirect(mon)
  188.   --term.clear()
  189.   term.setCursorPos(1,4)
  190. --  print("       Pyramid  ",monLevel,"/5")
  191.   print(" ~",math.floor(100*curCounter/monCount[monLevel]),"%")
  192.   term.redirect(term.native())
  193. end
  194. --os.sleep(1)
  195. --updateMon()
  196. --if true then return true end
  197.  
  198. ---------------------------------------
  199. ---- TABLES ---------------------------
  200. ---------------------------------------
  201.  
  202. ------------------------------------------------------------------------------
  203. -- rooms[] -------------------------------------------------------------------
  204.   -- type:                grass, labyrinth, lava, water, dungeon, ...
  205.   -- basic difficulty:    0=none/low, ...
  206.   -- underground blocked: true, false
  207.   -- room connections:    n,s,e,w,u(underground) and/or room numbers
  208.   -- distance from start: 4
  209.   -- is populated:        0,1,2, ...
  210.   -- chest likely-hood:   0.00 - 1.00
  211.  
  212.   -- grid:
  213.   -- rooms[x][z][parameters]
  214.   --
  215.   -- #rooms      =cRoomsGridX=number of rooms in x direction
  216.   -- #rooms[1]   =cRoomsGridZ=numbers of rooms in z direction
  217.   -- rooms[2][3] =room in grind pos 2,3
  218.   -- rooms[ix][iz]["interior"] = id of interiors[]
  219.   -- rooms[ix][iz]["fromEntrance"] = how far from entrance, entrance is 1, undefined is 0
  220.   -- rooms[ix][iz]["chest"]={{x,y,z,dmg},...}  = chest(s) that is/are placed in this room
  221. local rooms = {}            
  222. for ix=1,cRoomsGridX,1 do
  223.   rooms[ix]={}
  224.   for iz=1,cRoomsGridZ,1 do
  225.     rooms[ix][iz]={}
  226.     rooms[ix][iz]["chest"]={}
  227.     rooms[ix][iz]["fromEntrance"]=0 --default
  228.   end
  229. end
  230.  
  231. ------------------------------------------------------------------------------
  232. -- doors[] -------------------------------------------------------------------
  233. -- doors[x+1][z+1][1-3]: 1=has door in neg x dir (default = 0 = no door)
  234. --                       2=has door in neg z dir (default = 0 = no door)
  235. --                       3=has underground connection tbd.
  236. local doors ={}
  237. for ix=1,cRoomsGridX+1,1 do
  238.   doors[ix]={}
  239.   for iz=1,cRoomsGridZ+1,1 do
  240.     doors[ix][iz]={0,0,0}  --{door in -x dir, door in -z dir, underground}
  241.   end
  242. end
  243.  
  244. ------------------------------------------------------------------------------
  245. -- chests[] ------------------------------------------------------------------
  246. -- chests[i]["x"]/["y"]/["z"] = coordinates
  247. -- chests[i]["dmg"]           = damage value (direction not working atm)
  248. -- chests[i]["fromEntrance"]  = value taken over from room
  249. -- chests[i]["items"]={}
  250. --                   [1]["id"]=id to be used in command
  251. --                   [1]["count"]=counter to be used in command
  252. local chests ={}
  253.  
  254. ------------------------------------------------------------------------------
  255. -- chestItems[] --------------------------------------------------------------
  256. -- chestItems[i]["level"] = applied at which level
  257. -- chestItems[i]["chance"]= probability to be applied once(!), not per chest
  258. -- chestItems[i]["id"]    = item id
  259. -- chestItems[i]["count"] = how many (maybe do an array option)
  260. -- chestItems[i]["dmg"]   = damage value of the item
  261. local chestItems={}
  262. if true then
  263. -- level 1+
  264. chestItems[1] ={level={1,2},chance=0.4 ,id= 38,count={1,2,3},dmg=0}--poppy
  265. chestItems[2] ={level= 1   ,chance=0.3 ,id=391,count=1,dmg=0}--carrot
  266. chestItems[3] ={level= 1   ,chance=0.3 ,id=391,count=1,dmg=0}--carrot
  267. chestItems[4] ={level={1,2,3,4,5},chance=0.4 ,id=296,count={1,2,3},dmg=0}--wheat
  268. chestItems[5] ={level={1,2,3,4,5},chance=0.4 ,id=349,count={1,2},dmg=0}--raw fish
  269. chestItems[6] ={level={1,2},chance=0.2 ,id=346,count=1,dmg={20,40,60}}--fishing rod
  270. chestItems[7] ={level={1,2},chance=0.4 ,id=334,count={1,2,2},dmg=0}--leather
  271. chestItems[8] ={level={1,2},chance=0.4 ,id=334,count={1,2,2},dmg=0}--leather
  272. chestItems[9] ={level={1,2},chance=0.3 ,id=332,count={3,4,5,6},dmg=0}--snow ball
  273. chestItems[10]={level={1,2,3,4,5},chance=1  ,id=cMatId_WoodenSword,count=1,dmg={0,20,40}}--wooden sword
  274. chestItems[11]={level= 1   ,chance=0.5 ,id=272,count=1,dmg={90,100,110}}--stone sword
  275. chestItems[12]={level={1,2},chance=0.4 ,id=301,count=1,dmg={30,40,50}}--leather boots
  276. chestItems[13]={level={1,2},chance=0.4 ,id=298,count=1,dmg={30,40,50}}--leather cap
  277. chestItems[14]={level={1,2,3,4,5},chance=0.3 ,id=262,count={2,4,6},dmg=0}--arrow
  278. chestItems[15]={level={1,2,3,4,5},chance=0.1 ,id=375,count=1,dmg=0}--gold nugget
  279.  
  280. -- level 2+
  281. chestItems[16]={level={2,3,4,5},chance=1.0 ,id=263,count=1,dmg=1}--charcoal
  282. chestItems[17]={level={2,3,4,5},chance=0.3 ,id=260,count=1,dmg=0}--apple
  283. chestItems[18]={level= 2       ,chance=0.3 ,id=260,count=1,dmg=0}--apple
  284. chestItems[19]={level= 2       ,chance=0.4 ,id=353,count=1,dmg=0}--sugar
  285. chestItems[20]={level={2,3,4,5},chance=0.5 ,id=334,count={2,3,3},dmg=0}--leather
  286. chestItems[21]={level={2,3,4,5},chance=0.5 ,id=334,count={2,3,3},dmg=0}--leather
  287. chestItems[22]={level={2,3}    ,chance=0.4 ,id=300,count=1,dmg={10,20,50}}--leather pants
  288. chestItems[23]={level={2,3,4}  ,chance=0.4 ,id=299,count=1,dmg={10,20,50}}--leather chest/tunic
  289. chestItems[24]={level={2,3,4,5},chance=0.3 ,id=261,count=1,dmg={20,30,50}}--bow
  290. chestItems[25]={level={2,3,4,5},chance=0.5 ,id=272,count=1,dmg={70,80,90}}--stone sword
  291.  
  292. -- level 3+
  293. chestItems[26]={level={3,4,5}  ,chance=0.4 ,id=360,count={1,2,3,4},dmg=0}--melon
  294. chestItems[27]={level={3,4,5}  ,chance=0.3 ,id=265,count={1,2,3},dmg=0}--iron ingot
  295. chestItems[28]={level={3,4,5}  ,chance=0.4 ,id=306,count=1,dmg={100,150,200}}--iron helmet
  296. chestItems[29]={level={3,4,5}  ,chance=0.3 ,id=306,count=1,dmg={100,150,200}}--iron chest
  297. chestItems[30]={level={3,4,5}  ,chance=0.8 ,id=cMatId_DiscCat,count=1}--disc-cat, distraction item for jukebox
  298.  
  299. -- level 4+
  300. chestItems[31]={level={4,5}    ,chance=0.3 ,id=306,count=1,dmg={200,300,400}}--iron pants
  301. chestItems[32]={level={4,5}    ,chance=0.3 ,id=306,count=1,dmg={200,300,400}}--iron boots
  302. chestItems[33]={level={4,5}    ,chance=0.3 ,id=265,count={2,3,4},dmg=0}--iron ingot
  303.  
  304. end
  305.  
  306. ------------------------------------------------------------------------------
  307. -- interiors[] ---------------------------------------------------------------
  308. -- interiors["name"]        = name of interior
  309. -- interiors["chance"]      = if (randomly) selected this probability applies 0.0-1.0
  310. --                            default=1.0 for: interiors, sub-interiors, bases, blocks, summons
  311. -- interiors["base"]        = {x,y,z,mat,dmg} platform in room, usually at x1,x2,y,z1,z2=1,9,0,1,9
  312. --                            dmg=0 for: bases, blocks and summons
  313. -- interiors["blocks"][]    = {chance,x/{},y,z/{},mat,dmg,[extra]}
  314. -- interiors["summon"]      = summon an entity
  315. -- interiors["maxCount"][x] = how often is this design allowed on level x
  316. -- interiors["noExit"]      = true=>not allowed as interior in exit room (in defineRooms and for sub-interiors in xxx), nil=>okay
  317. -- interiors["noRandomLoot"]= (trapped_)chest will not get random loot (hence not reset, loosing existing loot)
  318. -- interiors["subinterior"] = not a block, but a set of blocks, identified via its name(!) or {name1, name2,...}
  319. ------- interiors["chest"][c]= {chance
  320. -- x1=1,x2=9,y=0,z1=1,z2=2
  321.  
  322. local interiors={}       -- room    interiors go from  1 to 10
  323.                          -- special interiors go from 11 to 11
  324. local interiorsData={}   -- for reading data file
  325. local cRoomInteriorMax =0--14  -- used for randomizing rooms
  326. local cRoomInteriorExit=cRoomInteriorMax+1
  327.  
  328. local intBase=0        -- base  count within interior
  329. local intBlock=0       -- block count within interior
  330.  
  331. -- changes that are not implemented in older data:
  332. -- 1) sub-interior do not need x/y/z
  333. -- 2) base may use x instead of x1=x2
  334.  
  335. ---------------------------------------
  336. ---- EARLY FUNCTIONS ------------------
  337. ---------------------------------------
  338.  
  339. term.clear() term.setCursorPos(1,1)
  340. local function askForInputText(textt)
  341.   local at=""
  342.   -- check prompting texts
  343.   if textt==nil then textt="Enter text:" end
  344.  
  345.   -- ask for input
  346.   write(textt)
  347.   at=read()
  348.   return at
  349. end
  350. ---------------------------------------
  351. local function debugPrint(intLevel,strPara1,strPara2,strPara3,strPara4,strPara5,strPara6,strPara7,strPara8,strPara9)
  352.   -- helper function for debug printing
  353.   -- step 1: check debug level
  354.   if not blnDebug then return end
  355.   if intLevel~= nil then
  356.     if intDebugLevel<tonumber(intLevel) then return end
  357.   end
  358.  
  359.   -- step 2: show message
  360.   local tmpPrintOut=strDebugPrompt
  361.   if strPara1 ~= nil then tmpPrintOut=tmpPrintOut..tostring(strPara1) end
  362.   if strPara2 ~= nil then tmpPrintOut=tmpPrintOut.."("..tostring(strPara2) end
  363.   if strPara3 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara3) end
  364.   if strPara4 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara4) end
  365.   if strPara5 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara5) end
  366.   if strPara6 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara6) end
  367.   if strPara7 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara7) end
  368.   if strPara8 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara8) end
  369.   if strPara9 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara9) end
  370.   if strPara2 ~= nil then tmpPrintOut=tmpPrintOut..")" end
  371.   print(tmpPrintOut)
  372.  
  373.   -- step 3: ask for key press every then and now
  374.   intDebugCounter=intDebugCounter+1
  375.   if intDebugCounter>=intDebugStopAt then
  376.     intDebugCounter=0
  377.     intDebugStopCounter=intDebugStopCounter+1
  378.     askForInputText("--> ("..intDebugStopCounter..") hit enter")
  379.   end
  380.  end
  381. ---------------------------------------
  382. local function readInterior(strDataLevel,tblData)
  383.   -- reads from either single function calls or (later) from files
  384.  
  385.   local intInterior   =#interiors
  386.   local intBase       =0--#interiors[intInterior]["base"]
  387.   local intBlock      =0
  388.   local intSubinterior=0--#interiors[intInterior]["subinterior"]
  389.   local intSummon     =0--#interiors[intInterior]["summon"]
  390.   local tmpText       =""
  391.  
  392.   if strDataLevel=="interiors" then
  393.     -- infos about last interior
  394.     if intInterior>1 then
  395.       debugPrint(3,"done int"..tostring(intInterior-1).."_"..interiors[intInterior-1]["name"].." ",#interiors[intInterior-1]["base"],#interiors[intInterior-1]["blocks"])--,#interiors[intInterior-1]["subinterior"])--,#interiors[intInterior-1]["summon"])--3
  396.     end
  397.    
  398.     -- start new interiors
  399.     --if intInterior==nil then intInterior=0 print("interior==nil") end
  400.     intInterior=intInterior+1
  401.     interiors[intInterior]=tblData
  402.     interiors[intInterior]["base"]={}
  403.     interiors[intInterior]["blocks"]={}
  404.     interiors[intInterior]["summon"]={}
  405.     interiors[intInterior]["subinterior"]={}
  406.     if interiors[intInterior]["chance"]==nil then interiors[intInterior]["chance"]=1 end
  407.     --debugPrint(0,"read int"..intInterior.."_"..interiors[intInterior]["name"])--3
  408.  
  409.     tmpText="new"
  410.   elseif strDataLevel=="base" then
  411.     -- read new base
  412.     intBase=#interiors[intInterior]["base"]+1
  413.     interiors[intInterior]["base"][intBase]=tblData
  414.     if interiors[intInterior]["base"][intBase]["dmg"]   ==nil then interiors[intInterior]["base"][intBase]["dmg"]   =0 end
  415.     if interiors[intInterior]["base"][intBase]["chance"]==nil then interiors[intInterior]["base"][intBase]["chance"]=1 end
  416.     tmpText=intBase
  417.   elseif strDataLevel=="blocks" then
  418.     -- read new block
  419.     intBlock=#interiors[intInterior]["blocks"]+1
  420.     interiors[intInterior]["blocks"][intBlock]=tblData
  421.     if interiors[intInterior]["blocks"][intBlock]["dmg"]   ==nil then interiors[intInterior]["blocks"][intBlock]["dmg"]   =0 end
  422.     if interiors[intInterior]["blocks"][intBlock]["chance"]==nil then interiors[intInterior]["blocks"][intBlock]["chance"]=1 end
  423.     tmpText=intBlock
  424.   elseif strDataLevel=="summon" then
  425.     -- read new summon
  426.     intSummon=#interiors[intInterior]["summon"]+1
  427.     interiors[intInterior]["summon"][intSummon]=tblData
  428.     if interiors[intInterior]["summon"][intSummon]["dmg"]   ==nil then interiors[intInterior]["summon"][intSummon]["dmg"]   =0 end
  429.     if interiors[intInterior]["summon"][intSummon]["chance"]==nil then interiors[intInterior]["summon"][intSummon]["chance"]=1 end
  430.     tmpText=intSummon
  431.   elseif strDataLevel=="subinterior" then
  432.     -- read new subinterior
  433.     intSubinterior=#interiors[intInterior]["subinterior"]+1
  434.     interiors[intInterior]["subinterior"][intSubinterior]=tblData
  435.     if interiors[intInterior]["subinterior"][intSubinterior]["chance"]==nil then interiors[intInterior]["subinterior"][intSubinterior]["chance"]=1 end
  436.     tmpText=intSubinterior
  437.   elseif strDataLevel=="set_cRoomInteriorMaxExit" then
  438.     -- read new subinterior
  439.     cRoomInteriorMax=#interiors
  440.     cRoomInteriorExit=cRoomInteriorMax+1
  441.     tmpText=strDataLevel
  442.   end
  443.  
  444.   if tmpText~="set_cRoomInteriorMaxExit" then
  445.     debugPrint(4,"read int"..intInterior.."_"..interiors[intInterior]["name"]..":",string.sub(strDataLevel,1,3).."_"..tmpText)--4
  446.   else
  447.     debugPrint(4,"cRoomInteriorMax="..cRoomInteriorMax,"cRoomInteriorExit="..cRoomInteriorExit)--4
  448.   end
  449. end
  450. ---------------------------------------
  451. local function cutString(strInput,strSeperator,blnDeleteSeparator)
  452. local tmpInt=string.find(strInput,strSeperator)
  453. local return1=""
  454. local return2=""
  455. -- ideas: add more than one separator
  456. debugPrint(4,strInput,strSeperator) --4
  457.  
  458.   return1=string.sub(strInput,1,tmpInt-1)
  459.   return2=string.sub(strInput,tmpInt+string.len(strSeperator))
  460.  
  461.   if blnDeleteSeparator==nil then blnDeleteSeparator=true end
  462.   if not blnDeleteSeparator then return2=strSeperator..return2 end
  463.  
  464.   return return1,return2
  465. end
  466. ---------------------------------------
  467. local function readInteriorData(strFile)
  468. debugPrint(2,"readInteriorData",strFile)--2
  469. local file = io.open(strFile, "r")
  470.   for line in file:lines() do
  471.     table.insert (interiorsData, line)
  472.   end
  473.   file:close()
  474. end
  475. ---------------------------------------
  476. local function transfereInteriorData()
  477. debugPrint(3,"transfereInteriorData",strFile)--3
  478. local tmpData
  479.  
  480.   for i=1,#interiorsData,1 do
  481.     tmpData=interiorsData[i]
  482.     interiorsData[i]=textutils.unserialize(interiorsData[i])
  483.    
  484.     -- step 1: valid data line?
  485.     if type(interiorsData[i])=="table" then
  486.       debugPrint(4,"Data table in "..i..":",interiorsData[i][1].."...")--4
  487.       readInterior(interiorsData[i][1],interiorsData[i][2])
  488.     else
  489.       debugPrint(3,"No data table in "..i..":",tmpData)--3
  490.     end
  491.     --askForInputText()
  492.   end
  493. end
  494.  
  495. ---------------------------------------
  496. ---- INTERIOR ROOM DEFINITIONS --------
  497. ---------------------------------------
  498.  
  499. readInteriorData("interiorData.lua")
  500. transfereInteriorData()
  501.  
  502. -- display read interiors
  503. debugPrint(0,"Interiors = "..cRoomInteriorMax.." ","1 to "..cRoomInteriorMax)
  504. debugPrint(0,"Sub-int.  = "..#interiors-cRoomInteriorMax.." ",tostring(cRoomInteriorMax+1).." to "..#interiors)
  505.  
  506. -- initialize counter for implemented interiors
  507. for i = 1,#interiors,1 do countInteriors[i]=0 end
  508.  
  509. ---------------------------------------
  510. ---- FUNCTIONS ------------------------
  511. ---------------------------------------
  512. -- List of functions:
  513. --local function askForInputText(textt)
  514. --local function debugPrint(intLevel,strPara1,strPara2,strPara3,strPara4,strPara5,strPara6,strPara7,strPara8,strPara9)
  515. --local function baseCoordinates(xRoom,zRoom)
  516. --local function pullTaskComplete()
  517. --local function makeStringCommand(par1,par2,par3,par4,par5,par6,par7,par8,par9)
  518. --local function clearRange(xx,yy,zz,optDx,optDy,optDz)
  519. --local function clearRoom(xx,yy,zz)
  520. --local function resetRooms()
  521. --local function randomDoorId()
  522. --local function randomDoorId()
  523. --local function ensureCornerDoors(doorX1,doorZ1,doorS1,doorX2,doorZ2,doorS2)
  524. --local function displayDistance()
  525. --local function updateDistance()
  526. --local function addNewDoor()
  527. --local function defineDoors()
  528. --local function implementDoors()
  529. --local function defineRooms()
  530. --local function implementInterior(xRoom,zRoom,interiorID)
  531. --local function implementRooms()
  532. --local function addItemToChest(intChest,intItemId,intItemCount,intItemDmg)
  533. --local function defineGoldDistribution()
  534. --local function defineChestItems()
  535. --local function defineKeyItemDistribution()
  536. --local function implementChestItems()
  537.  
  538. local function askForInputText(textt)
  539.   local at=""
  540.   -- check prompting texts
  541.   if textt==nil then textt="Enter text:" end
  542.  
  543.   -- ask for input
  544.   write(textt)
  545.   at=read()
  546.   return at
  547. end
  548. ---------------------------------------
  549. local function debugPrint(intLevel,strPara1,strPara2,strPara3,strPara4,strPara5,strPara6,strPara7,strPara8,strPara9)
  550.   -- helper function for debug printing
  551.   -- step 1: check debug level
  552.   if not blnDebug then return end
  553.   if intLevel~= nil then
  554.     if intDebugLevel<tonumber(intLevel) then return end
  555.   end
  556.  
  557.   -- step 2: show message
  558.   local tmpPrintOut=strDebugPrompt
  559.   if strPara1 ~= nil then tmpPrintOut=tmpPrintOut..tostring(strPara1) end
  560.   if strPara2 ~= nil then tmpPrintOut=tmpPrintOut.."("..tostring(strPara2) end
  561.   if strPara3 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara3) end
  562.   if strPara4 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara4) end
  563.   if strPara5 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara5) end
  564.   if strPara6 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara6) end
  565.   if strPara7 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara7) end
  566.   if strPara8 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara8) end
  567.   if strPara9 ~= nil then tmpPrintOut=tmpPrintOut..","..tostring(strPara9) end
  568.   if strPara2 ~= nil then tmpPrintOut=tmpPrintOut..")" end
  569.   print(tmpPrintOut)
  570.  
  571.   -- step 3: ask for key press every then and now
  572.   intDebugCounter=intDebugCounter+1
  573.   if intDebugCounter>=intDebugStopAt then
  574.     intDebugCounter=0
  575.     intDebugStopCounter=intDebugStopCounter+1
  576.     askForInputText("--> ("..intDebugStopCounter..") hit enter")
  577.   end
  578.  end
  579. ---------------------------------------
  580. local function baseCoordinates(xRoom,zRoom)
  581.   -- returns start coordinates of a room (left, bottom corner, one above floor level)
  582.   debugPrint(4,"baseCoordinates",xRoom,zRoom)
  583.   return xHome+cOffsetX+(xRoom-1)*(cRoomDepth-1), yHome+cOffsetY, zHome+cOffsetZ+(zRoom-1)*(cRoomWidth-1)
  584. end
  585. ---------------------------------------
  586. local function pullTaskComplete()
  587.   while true do
  588.     os.pullEvent("task_complete")
  589.     curCommands = curCommands - 1
  590.     curCounterComplete=curCounterComplete+1
  591.     --write("*")
  592.   end
  593. end
  594. ---------------------------------------
  595. local function makeStringCommand(par1,par2,par3,par4,par5,par6,par7,par8,par9)
  596. local strCommand=""
  597.   if par1~=nil then
  598.     strCommand=tostring(par1).." "
  599.     if par2~=nil then
  600.       strCommand=strCommand..tostring(par2).." "
  601.       if par3~=nil then
  602.         strCommand=strCommand..tostring(par3).." "
  603.         if par4~=nil then
  604.           strCommand=strCommand..tostring(par4).." "
  605.           if par5~=nil then
  606.             strCommand=strCommand..tostring(par5).." "
  607.             if par6~=nil then
  608.               strCommand=strCommand..tostring(par6).." "
  609.               if par7~=nil then
  610.                 strCommand=strCommand..tostring(par7).." "
  611.                 if par8~=nil then
  612.                   strCommand=strCommand..tostring(par8).." "
  613.                   if par9~=nil then
  614.                     strCommand=strCommand..tostring(par9).." "
  615.                   end
  616.                 end
  617.               end
  618.             end
  619.           end
  620.         end
  621.       end
  622.     end  
  623.   end
  624.   return strCommand
  625. end
  626. ---------------------------------------
  627. local function execCommand(par1,par2,par3,par4,par5,par6,par7,par8,par9)
  628.   -- command execution is done here
  629.   -- a) to hinder exceeding of task limit
  630.   -- b) (later) to allow competitive 2 player mode
  631.  
  632.   parallel.waitForAny(
  633.                         pullTaskComplete,
  634.            
  635.                         function()
  636.                             while curCommands >= maxCommands do
  637.         --behalten                    print("execCom:",curCommands," ",curCounter," ",curCounterComplete)
  638.                               updateMon()
  639.                               --debugPrint(0,"execCommand",curCommands)
  640.                               os.pullEvent("task_complete")
  641.                             end
  642.                             --write(par1)
  643.                             if part1=="setblock" then
  644.                               --commands.setBlock(par2,par3,par4,par5,par6,par7,par8,par9) -- hatte hier async vergessen
  645.                               commands.async.setBlock(par2,par3,par4,par5,par6,par7,par8,par9) -- hatte hier async vergessen
  646.                             else
  647.                            
  648.                               commands.execAsync(makeStringCommand(par1,par2,par3,par4,par5,par6,par7,par8,par9))
  649.                             end
  650.                             curCounter=curCounter+1
  651.                             curCommands = curCommands + 1
  652.                         end
  653.                       )
  654. end
  655. ---------------------------------------
  656.  
  657. local function clearRange(x1,y1,z1,x2,y2,z2)
  658.   -- clears defined area
  659.   -- uses absolute parameters
  660.   debugPrint(0,"clearRange",x1,y1,z1,x2,y2,z2)--1
  661.   --os.sleep(10)
  662.   if x2==nil then x2=x1 end
  663.   if y2==nil then y2=y1 end
  664.   if z2==nil then z2=z1 end
  665.  
  666.   for ix=x1,x2,1 do
  667.     for iy=y2,y1,-1 do
  668.       for iz=z1,z2,1 do
  669.         execCommand("setblock",ix,iy,iz,"minecraft:air",0,"replace")
  670.       end
  671.     end
  672.     --os.sleep(0)
  673.   end
  674.   return true
  675. end
  676.  
  677. ---------------------------------------
  678. local function clearRoom(xR,zR)
  679.   -- resets room to basic layout, i.e. walls, floor and ceiling
  680.   -- avoids double setting of walls, i.e. not usable for single room reset
  681.   --                                 anyways wouldn't work because of things on walls
  682.   debugPrint(1,"clearRoom",xR,zR)
  683.   local basisX=0
  684.   local basisY=0
  685.   local basisZ=0
  686.   basisX,basisY,basisZ=baseCoordinates(xR,zR)
  687.  
  688.   -- step 1: wall north (left)
  689.   for ix=basisX,basisX+cRoomDepth-1,1 do
  690.     for iy=basisY,basisY+cRoomHeight,1 do
  691.       execCommand("setblock",ix,iy,basisZ,cRoomMaterial,cRoomMaterialDmg)
  692.     end
  693.   end  
  694.   -- step 2: wall south (right)
  695.   if zR==#rooms[1] then
  696.     for ix=basisX,basisX+cRoomDepth-1,1 do
  697.       for iy=basisY,basisY+cRoomHeight,1 do
  698.         execCommand("setblock",ix,iy,basisZ+cRoomWidth-1,cRoomMaterial,cRoomMaterialDmg)
  699.       end
  700.     end
  701.   else
  702.     -- no need to double set the wall
  703.   end
  704.   -- step 3: walls west (front)
  705.   for iz=basisZ,basisZ+cRoomDepth-2,1 do
  706.     for iy=basisY,basisY+cRoomHeight,1 do  
  707.       execCommand("setblock",basisX,iy,iz,cRoomMaterial,cRoomMaterialDmg)
  708.     end
  709.   end
  710.  
  711.   -- step 4: wall east (back)
  712.   if xR==#rooms then
  713.     for iz=basisZ,basisZ+cRoomDepth-2,1 do
  714.       for iy=basisY,basisY+cRoomHeight,1 do
  715.         execCommand("setblock",basisX+cRoomWidth-1,iy,iz,cRoomMaterial,cRoomMaterialDmg)
  716.       end
  717.     end
  718.   else
  719.     -- no need to double set the wall
  720.   end
  721.   -- step 5: floor and ceiling
  722.   for ix=basisX,basisX+cRoomDepth-1,1 do
  723.     for iz=basisZ,basisZ+cRoomDepth-1,1 do
  724.       execCommand("setblock",ix,basisY,iz,cRoomMaterial,cRoomMaterialDmg)
  725.       if not blnNoGlassRoof then
  726.         execCommand("setblock",ix,basisY+cRoomHeight+1,iz,cRoomMaterialCeiling,cRoomMaterialCeilingDmg)
  727.       end
  728.     end
  729.   end  
  730.  
  731.   return true
  732. end
  733. ---------------------------------------
  734. local function resetRooms()--xx,yy,zz)
  735.   -- prepare fresh and empty default rooms
  736.   debugPrint(1,"resetRooms")
  737.   local basisX=0
  738.   local basisY=0
  739.   local basisZ=0
  740.   basisX,basisY,basisZ=baseCoordinates(1,1)  
  741.  
  742.   -- step 1: clear whole labyrinth in one go (incl. roof and underground)
  743.   if blnClearBeforeBuild then
  744.     -- waterview space
  745.     clearRange(basisX+4,basisY+7  ,basisZ+4,basisX+#rooms*(cRoomDepth-1)-4,basisY+cRoomHeight+1+4,basisZ+#rooms[1]*(cRoomWidth-1)-4)
  746.     -- regular space
  747.     clearRange(basisX,  basisY-3-2,basisZ  ,basisX+#rooms*(cRoomDepth-1),  basisY+cRoomHeight+1  ,basisZ+#rooms[1]*(cRoomWidth-1))
  748.   end
  749.  
  750.   if blnJustClear then return end
  751.  
  752.   -- step 2: resets the whole room grid
  753.   debugPrint(1,"resetRooms")--,xx,yy,zz)
  754.    for xRoom=1,#rooms,1 do
  755.     for zRoom=1,#rooms[1],1 do
  756.       clearRoom(xRoom,zRoom)
  757.       --os.sleep(0.1)
  758.     end
  759.   end
  760.   --for xRoom=0,#rooms-1,1 do
  761.    -- for zRoom=0,#rooms[1]-1,1 do
  762.      -- clearRoom(xx+xRoom*(cRoomDepth-1),yy,zz+zRoom*(cRoomWidth-1))
  763.     --end
  764. --  end
  765. end
  766. ---------------------------------------
  767. local function randomDoorId()
  768.   -- returns a door identifier
  769.   -- so far only a random nummber generator
  770.   debugPrint(4,"randomDoorId")
  771.   return math.random(1,2)  -- random door
  772.                            -- 1=air
  773.                            -- 2=wooden door
  774.                            -- 9=iron door for entrance(not a random door)
  775.                            -- exit needs 1=air, iron door is placed by sub-interior
  776. end
  777. ---------------------------------------
  778. local function ensureCornerDoors(doorX1,doorZ1,doorS1,doorX2,doorZ2,doorS2)
  779.   -- ensures that at least one of the two walls has a door
  780.   debugPrint(1,"ensureCornerDoors",doorX1,doorZ1,doorS1,doorX2,doorZ2,doorS2)--1
  781.   debugPrint(4,"doorX1,doorZ1,doorS1=",doorX1,doorZ1,doorS1," ",doors[doorX1][doorZ1][doorS1])--4
  782.   debugPrint(4,"doorX2,doorZ2,doorS2=",doorX2,doorZ2,doorS2," ",doors[doorX2][doorZ2][doorS2])--4
  783.   if (doors[doorX1][doorZ1][doorS1]==0) and (doors[doorX2][doorZ2][doorS2]==0) then
  784.     -- both walls do not have a door: put in a door
  785.     debugPrint(2,"...need additional door")
  786.     if math.random() <=0.5 then
  787.       doors[doorX1][doorZ1][doorS1]=randomDoorId()
  788.     else
  789.       doors[doorX2][doorZ2][doorS2]=randomDoorId()
  790.     end
  791.   end
  792. end
  793. ---------------------------------------
  794. local function displayDistance()
  795.   -- prints room distance from entrance
  796.   print("Room distance from entrance:-----")
  797.   for ix=#rooms,1,-1 do
  798.     for iz=1,#rooms[1],1 do
  799.       write(tostring(rooms[ix][iz]["fromEntrance"]).." ")
  800.     end
  801.     print()
  802.   end
  803. end
  804. ---------------------------------------
  805. local function updateDistance()
  806.   -- updates the "fromEntrance" entry of all rooms
  807.  
  808.   local blnAllAssigned = false -- true if no room has "fromEntrance"=0
  809.   local blnNoChanges   = true  -- false if in one go a room changed
  810.   local countRoomsNull = 0     -- final check how many are assigned but 0=0
  811.   local tmpFromExit = 0 local tmpFromExit2 = 0
  812.   local tmpNeighbor = 0 local tmpNeighbor2 = 0
  813.   local tmpCounter=0
  814.   local tmpCounterMax=20
  815.  
  816.   repeat
  817.     -- check may runs
  818.     tmpCounter=tmpCounter+1
  819.     if tmpCounter>tmpCounterMax then
  820.       --debugPrint(0,"updateDistance2",blnAllAssigned,blnNoChanges,tmpCounter)
  821.       break
  822.     end
  823.    
  824.     blnAllAssigned = true  -- assumption
  825.     blnNoChanges   = true  -- so far
  826.  
  827.  
  828.     -- step 1: check bottom neighbor ---------------------------------------
  829.     for ix=2,#rooms,1 do
  830.       for iz=1,#rooms[1],1 do
  831.         -- get data
  832.         tmpFromExit=rooms[ix][iz]["fromEntrance"]
  833.         -- check neighbor
  834.         if doors[ix][iz][1]~=0 then
  835.           -- neighbor at bottom
  836.           tmpNeighbor=rooms[ix-1][iz]["fromEntrance"]
  837.           if tmpFromExit==0 then
  838.             -- I'm not assigned yet
  839.             if tmpNeighbor==0 then
  840.               -- both not assigned
  841.               blnAllAssigned = false
  842.             else
  843.               -- I'm one more far away than my neighbor
  844.               rooms[ix][iz]["fromEntrance"]=tmpNeighbor+1
  845.               blnNoChanges = false
  846.             end
  847.           else
  848.             -- I'm assigned already
  849.             if tmpNeighbor==0 then
  850.               -- I may assign my neighbor
  851.               rooms[ix-1][iz]["fromEntrance"]=tmpFromExit+1
  852.               blnNoChanges = false
  853.             else
  854.               -- hm, which one is closer?
  855.               tmpFromExit2=math.min(tmpFromExit,tmpNeighbor+1)
  856.               tmpNeighbor2=math.min(tmpNeighbor,tmpFromExit+1)
  857.               if tmpFromExit2<tmpFromExit then
  858.                 -- I'm closer now
  859.                 rooms[ix][iz]["fromEntrance"]=tmpFromExit2
  860.                 blnNoChanges = false
  861.               end
  862.               if tmpNeighbor2<tmpNeighbor then
  863.                 -- Neighbor is closer now
  864.                 rooms[ix-1][iz]["fromEntrance"]=tmpNeighbor2
  865.                 blnNoChanges = false
  866.               end            
  867.             end
  868.           end
  869.         end
  870.       end
  871.     end
  872.    
  873.     -- step 2: check left neighbor ---------------------------------------
  874.     for ix=1,#rooms,1 do
  875.       for iz=2,#rooms[1],1 do
  876.         -- get data
  877.         tmpFromExit=rooms[ix][iz]["fromEntrance"]
  878.         -- check neighbor
  879.         if doors[ix][iz][2]~=0 then
  880.           -- neighbor to the left
  881.           tmpNeighbor=rooms[ix][iz-1]["fromEntrance"]
  882.           if tmpFromExit==0 then
  883.             -- I'm not assigned yet
  884.             if tmpNeighbor==0 then
  885.               -- both not assigned
  886.               blnAllAssigned = false
  887.             else
  888.               -- I'm one more far away than my neighbor
  889.               rooms[ix][iz]["fromEntrance"]=tmpNeighbor+1
  890.               blnNoChanges = false
  891.             end
  892.           else
  893.             -- I'm assigned already
  894.             if tmpNeighbor==0 then
  895.               -- I may assign my neighbor
  896.               rooms[ix][iz-1]["fromEntrance"]=tmpFromExit+1
  897.               blnNoChanges = false
  898.             else
  899.               -- hm, which one is closer?
  900.               tmpFromExit2=math.min(tmpFromExit,tmpNeighbor+1)
  901.               tmpNeighbor2=math.min(tmpNeighbor,tmpFromExit+1)
  902.               if tmpFromExit2<tmpFromExit then
  903.                 -- I'm closer now
  904.                 rooms[ix][iz]["fromEntrance"]=tmpFromExit2
  905.                 blnNoChanges = false
  906.               end
  907.               if tmpNeighbor2<tmpNeighbor then
  908.                 -- Neighbor is closer now
  909.                 rooms[ix][iz-1]["fromEntrance"]=tmpNeighbor2
  910.                 blnNoChanges = false
  911.               end            
  912.             end
  913.           end
  914.         end
  915.       end
  916.     end
  917.   until (blnAllAssigned and blnNoChanges)
  918.  
  919.   -- step 3 quick check all rooms for 0
  920.   -- hint: if a 0 room has no doors it might get skipped
  921.   for ix=1,#rooms,1 do
  922.     for iz=1,#rooms[1],1 do
  923.       if rooms[ix][iz]["fromEntrance"]==0 then countRoomsNull=countRoomsNull+1 end
  924.     end
  925.   end
  926.      
  927.   debugPrint(1,"updateDistance",blnAllAssigned,blnNoChanges,tmpCounter,countRoomsNull)
  928.  
  929.   if intDebugLevel>=5 then
  930.     displayDistance()
  931.     askForInputText("for debugging...")
  932.   end
  933.  
  934.   -- return success and number of tries
  935.   if countRoomsNull==0 then
  936.     return true, tmpCounter
  937.   else
  938.     return false, tmpCounter -- may be false if tmpCounterMax triggered
  939.   end
  940.  
  941. end
  942. ---------------------------------------
  943. local function addNewDoor()
  944.   -- adds one new door in order to make all rooms available
  945.   -- strategy: go from up downwards (should be randomized in a clever way later)
  946.   --           produce only door if exactly one of the two rooms is rated 0
  947.   debugPrint(1,"addNewDoor")
  948.   local iRoom=0
  949.   local iNeighbor=0
  950.  
  951.   -- loop through all rooms
  952.   for ix=#rooms,1,-1 do
  953.     for iz=#rooms[1],1,-1 do
  954.       -- step 1 check door down (side=1)
  955.       if ix~=1 then -- not first row
  956.         iRoom    =rooms[ix][iz]["fromEntrance"]
  957.         iNeighbor=rooms[ix-1][iz]["fromEntrance"]
  958.         if (iRoom==0 and iNeighbor~=0) or (iRoom~=0 and iNeighbor==0) then
  959.           -- gotcha!
  960.           doors[ix][iz][1]=randomDoorId
  961.           debugPrint(2,"..added new door",ix,iz,1)
  962.           return true
  963.         end
  964.       end
  965.       -- step 2 check door left (side=2)
  966.       if iz~=1 then -- not left row
  967.         iRoom    =rooms[ix][iz]["fromEntrance"]
  968.         iNeighbor=rooms[ix][iz-1]["fromEntrance"]
  969.         if (iRoom==0 and iNeighbor~=0) or (iRoom~=0 and iNeighbor==0) then
  970.           -- gotcha!
  971.           doors[ix][iz][2]=randomDoorId
  972.           debugPrint(2,"..added new door",ix,iz,2)
  973.           return true
  974.         end
  975.       end    
  976.     end
  977.   end
  978. end
  979. ---------------------------------------
  980. local function defineDoors()
  981.   -- defines where there are connections between rooms
  982.   -- including underground tunnels
  983.   -- keep in mind #rooms+1=#doors!
  984.   -- HINT: so far only kind of a simulation by choosing a predefined set / rnd
  985.   debugPrint(1,"defineDoors")
  986.  
  987.   local cDoorProability=0.4--0.2 --0.5-- chance to get any door in a wall
  988.   local tmpEntranceZ=math.floor(#rooms[1]/2+0.5) -- middle of front
  989.   local tmpExitZ=math.random(1,#rooms[1]) --rnd on back wall
  990.  
  991.  
  992.   -- step 1: random doors
  993.   -- so far only random without any checks or any predefined sets
  994.   for xD=1,#doors,1 do
  995.     for zD=1,#doors[1],1 do
  996.       for iSide=1,2,1 do
  997.         if math.random() <= cDoorProability then
  998.           doors[xD][zD][iSide]=randomDoorId()
  999.         end
  1000.       end
  1001.     end
  1002.   end
  1003.  
  1004.   -- step 2: delete doors at outer walls
  1005.   -- no walls at back and front
  1006.   for iz=1,#doors[1],1 do
  1007.     doors[1][iz][1]=0       -- lower wall
  1008.     doors[#doors][iz][1]=0  -- upper wall
  1009.     doors[#doors][iz][2]=0  -- wall between not existing rooms
  1010.   end
  1011.   for ix=1,#doors,1 do
  1012.     doors[ix][1][2]=0       -- left wall
  1013.     doors[ix][#doors[1]][2]=0  -- right wall
  1014.     doors[ix][#doors[1]][1]=0  -- wall between not existing rooms
  1015.   end
  1016.  
  1017.   -- step 3: entrance door
  1018.   doors[1][tmpEntranceZ][1]=9              -- 9= iron door
  1019.   rooms[1][tmpEntranceZ]["fromEntrance"]=1 -- entrance
  1020.   entrRoomZ=tmpEntranceZ
  1021.    
  1022.   -- step 4: exit door
  1023.   doors[#doors][tmpExitZ][1]=1             -- exit needs here 1=air
  1024.   exitRoomZ=tmpExitZ                       -- iron door is set by sub-interior
  1025.  
  1026.   -- step 5: check corners to have at least one door
  1027.   -- room 1,1
  1028.   ensureCornerDoors(2,1,1,1,2,2)
  1029.   -- room n,1
  1030.   ensureCornerDoors(#doors-1,1,1,#doors-1,2,2)
  1031.   -- room 1,n
  1032.   ensureCornerDoors(2,#doors[1]-1,1,1,#doors[1]-1,2)
  1033.   -- room n,n
  1034.   ensureCornerDoors(#doors-1,#doors[1]-1,1,#doors-1,#doors[1]-1,2)
  1035.  
  1036.   -- step 6: ensure all rooms are accessible
  1037.   while not updateDistance() do --()~=1 do
  1038.     addNewDoor()  
  1039.   end
  1040.   displayDistance()
  1041.  
  1042.  
  1043.   if blnDebug and false then
  1044.   local tmpCount=0
  1045.     print("doors[x][y][w]:----------------")
  1046.     for xD=1,#doors,1 do
  1047.       for zD=1,#doors[1],1 do
  1048.         write("["..tostring(xD).."]["..tostring(zD).."]")
  1049.         for wD=1,2,1 do
  1050.           write(" "..tostring(wD).."="..tostring(doors[xD][zD][wD]))
  1051.         end
  1052.         tmpCount=tmpCount+1
  1053.         if tmpCount>=3 then
  1054.           tmpCount=0
  1055.           print()
  1056.         else
  1057.           write(" ")
  1058.         end
  1059.       end
  1060.     end
  1061.     if tmpCount~=0 then print() end
  1062.   end  
  1063.  
  1064.  
  1065. end
  1066. ---------------------------------------
  1067. local function implementDoors()
  1068.   -- implements the defined doors
  1069.   debugPrint(1,"implementDoors")
  1070.   local basisX=0
  1071.   local basisY=0
  1072.   local basisZ=0
  1073.   local tmpDoor=0
  1074.  
  1075.   -- so far only basic doorway
  1076.   for xD=1,#doors,1 do
  1077.     for zD=1,#doors[1],1 do
  1078.       for iSide=1,2,1 do
  1079. --if doors[xD][zD][iSide]==3 then print("Found test door at (",xD,",",zD,",",iSide,")") end
  1080.      
  1081.         if doors[xD][zD][iSide]~=0 then -- some kind of door
  1082.           basisX,basisY,basisZ=baseCoordinates(xD,zD)
  1083.           tmpDoor=0
  1084.          -- basisY=basisY+1 --hm
  1085.          
  1086. --[[ door  orientation info:   
  1087. 1) place lower half: it determines the orientation and if it is open
  1088. 2) place upper half: it determines the hinge
  1089.  
  1090. lower part: direction: closed, open
  1091.             North: 1, 5
  1092.             South: 3, 7
  1093.             East: 2, 6
  1094.             West: 0, 4
  1095. upper part: hinge:
  1096.             Right: 8
  1097.             Left: 9
  1098. e.g.: /setblock 0 64 0 wooden_door 1 replace
  1099.       /setblock 0 65 0 wooden_door 8 replace
  1100. ]]--     
  1101.           -- need to do this more general in a function
  1102.           if iSide==1 then -- door in x-wall
  1103.             -- a wall separating the room towards neg. x
  1104.             if doors[xD][zD][iSide]==2 then
  1105.               -- wooden door   
  1106.               -- facing east or west
  1107.               tmpDoor=math.random(0,1)*2
  1108.               -- closed(3/4) or open (1/4)
  1109.               tmpDoor=tmpDoor+math.floor(math.random()+.25)*4
  1110.               -- set lower part
  1111.               execCommand("setblock",basisX,basisY+1,basisZ+5,"minecraft:wooden_door",tmpDoor,"remove")
  1112.               -- set upper part (incl. hinge right or left)
  1113.               tmpDoor=math.random(8,9)
  1114.               execCommand("setblock",basisX,basisY+2,basisZ+5,"minecraft:wooden_door",tmpDoor,"remove")              
  1115.             elseif doors[xD][zD][iSide]==3 then
  1116.               -- test door (disabled)
  1117.               execCommand("setblock",basisX,basisY+1,basisZ+5,"minecraft:wool",14,"remove")
  1118.               execCommand("setblock",basisX,basisY+2,basisZ+5,"minecraft:wool",14,"remove")
  1119.             elseif doors[xD][zD][iSide]==9 then
  1120.               -- iron door for entrance or exit, i.e. always side=1
  1121.  
  1122.               -- set lower part
  1123.               execCommand("setblock",basisX,basisY+1,basisZ+5,"minecraft:iron_door",0,"remove")
  1124.               -- set upper part (incl. hinge right or left)
  1125.               tmpDoor=math.random(8,9)
  1126.               execCommand("setblock",basisX,basisY+2,basisZ+5,"minecraft:iron_door",tmpDoor,"remove")                
  1127.              
  1128.              
  1129.             else
  1130.               -- only air
  1131.               execCommand("setblock",basisX,basisY+1,basisZ+5,0,0,"remove")
  1132.               execCommand("setblock",basisX,basisY+2,basisZ+5,0,0,"remove")
  1133.             end
  1134.           elseif iSide==2 then -- door in z-wall
  1135.             -- a wall separating the room towards neg. z
  1136.             if doors[xD][zD][iSide]==2 then
  1137.               -- wooden door
  1138.               -- facing north or south
  1139.               tmpDoor=math.random(0,1)*2+1
  1140.               -- closed(3/4) or open (1/4)
  1141.               tmpDoor=tmpDoor+math.floor(math.random()+0.25)*4
  1142.               -- set lower part
  1143.               execCommand("setblock",basisX+5,basisY+1,basisZ,"minecraft:wooden_door",tmpDoor,"remove")
  1144.               -- set upper part (incl. hinge right or left)
  1145.               tmpDoor=math.random(8,9)
  1146.               execCommand("setblock",basisX+5,basisY+2,basisZ,"minecraft:wooden_door",tmpDoor,"remove")    
  1147.             elseif doors[xD][zD][iSide]==3 then
  1148.               -- test
  1149.               execCommand("setblock",basisX+5,basisY+1,basisZ,"minecraft:wool",14,"remove")
  1150.               execCommand("setblock",basisX+5,basisY+2,basisZ,"minecraft:wool",14,"remove")          
  1151.             else
  1152.               -- only air
  1153.               execCommand("setblock",basisX+5,basisY+1,basisZ,  0,0,"remove")  
  1154.               execCommand("setblock",basisX+5,basisY+2,basisZ,  0,0,"remove")  
  1155.             end
  1156.           else
  1157.             debugPrint(0,"Unexpected value in implemtnetDoors()")
  1158.           end
  1159.         end
  1160.       end
  1161.     end
  1162.   end  
  1163. end
  1164. ---------------------------------------
  1165. local function defineRooms()
  1166.   -- chooses interior for rooms & checks applicability
  1167.   debugPrint(1,"defineRooms")
  1168.   local tmpInterior=0
  1169.   local tmpGo=true
  1170.   local tmpStr=""
  1171.  
  1172.   for xRoom=1,#rooms,1 do
  1173.     for zRoom=1,#rooms[1],1 do
  1174.       -- step 1: randomize interior + apply probability
  1175.       repeat -- random chance
  1176.         repeat -- max counter
  1177.           repeat -- check entrance and exit
  1178.             impInterior=math.random(1,cRoomInteriorMax)  -- =math.random(1,#interiors) not this due to extra interiors     
  1179.             if intDebugLevel>=3 then tmpStr="["..xRoom..","..zRoom.."] try:"..interiors[impInterior]["name"].."("..countInteriors[impInterior].."/"..interiors[impInterior]["maxCount"][intLabLevel]..")" write(tmpStr) end
  1180.             tmpGo=true       --3
  1181.             -- step 2: check noExit
  1182.             if xRoom==#rooms and zRoom==exitRoomZ then
  1183.               if interiors[impInterior]["noExit"]~=nil then
  1184.                 tmpGo=false
  1185.                 if intDebugLevel>=0 then write(interiors[impInterior]["name"].." > no exit!") end --3
  1186.               else
  1187.                 if intDebugLevel>=3 then write(">exit ok") end --3
  1188.               end
  1189.             end
  1190.             -- step 3: check noEntrance
  1191.             if xRoom==1 and zRoom==entrRoomZ then
  1192.               if interiors[impInterior]["noEntrance"]~=nil then
  1193.                 tmpGo=false
  1194.                 if intDebugLevel>=0 then write(interiors[impInterior]["name"].." > no entrance!") end -- 3
  1195.               else
  1196.                 if intDebugLevel>=3 then write(">entrance ok") end  --3
  1197.               end
  1198.             end        
  1199.            
  1200.           until tmpGo
  1201. --print(impInterior," ",intLabLevel," ",countInteriors[impInterior])
  1202.           -- check maxCount
  1203.         until countInteriors[impInterior]<interiors[impInterior]["maxCount"][intLabLevel]
  1204.         if intDebugLevel>=3 then write(">max") end 
  1205.         -- random chance
  1206.         --if intDebugLevel>=3 then write(".") end
  1207.       until math.random()<interiors[impInterior]["chance"]
  1208.       if intDebugLevel>=3 then print(">rnd ok") end
  1209.       --if intDebugLevel>=3 then print(impInterior) end
  1210.       --found interior id for this room
  1211.       rooms[xRoom][zRoom]["interior"]=impInterior
  1212.       -- count new interior
  1213.       countInteriors[impInterior]=countInteriors[impInterior]+1
  1214.     end
  1215.   end
  1216. end
  1217. ---------------------------------------
  1218. local function implementInterior(xRoom,zRoom,interiorID)
  1219.   -- generic function to implement an interior in a room using the interiors array structure
  1220.   -- implements the defined rooms
  1221.   -- recursive call by sub-interiors
  1222.   local basisX=0
  1223.   local basisY=0
  1224.   local basisZ=0
  1225.  
  1226.   local tmpC=0  -- chance
  1227.   local tmpX=0  -- x
  1228.   local tmpY=0  -- y
  1229.   local tmpZ=0  -- z
  1230.   local tmpM="" -- material
  1231.   local tmpD=0  -- damage
  1232.   local tmpE="" -- extra like "{Items:[:{Count:1,Slot:0,id:35,Damage:1}]}"
  1233.     local tmpE_new_all=""
  1234.     local tmpE_new={}
  1235.     tmpE_new[1]=""
  1236.     tmpE_new[2]=""
  1237.     tmpE_new[3]=""
  1238.     tmpE_new[4]=""  -- rest
  1239.     tmpE_num=0
  1240.   local tmpB=0  -- base
  1241.   local tmpBx1=0-- base x1
  1242.   local tmpBx2=0-- base x2
  1243.   local tmpBy1=0-- base y1
  1244.   local tmpBy2=0-- base y2
  1245.   local tmpBz1=0-- base z1
  1246.   local tmpBz2=0-- base z2
  1247.   local tmpBD=0 -- base dmg
  1248.   local tmpSubName="" -- name of subinterior
  1249.  
  1250.   local blnFoundSubinterior=false
  1251.  
  1252.       debugPrint(1,".."..interiors[interiorID]["name"],xRoom,zRoom)
  1253.       basisX,basisY,basisZ=baseCoordinates(xRoom,zRoom)  
  1254.      
  1255.       -- step 1: check for noExit=true in case of sub-interiors
  1256.       if xRoom==#rooms and zRoom==exitRoomZ then
  1257.         -- check noExit
  1258.         -- regular interiors should already be taken care of in defineRooms
  1259.         -- here focus is on sub-interiors (e.g., to not make TNT explode near redstone)
  1260.         if interiors[interiorID]["noExit"]~=nil then
  1261.           debugPrint(0,"..not doing interior at exit!",interiors[interiorID]["name"])
  1262.           return
  1263.         else
  1264.           -- everything is okay              
  1265.         end
  1266.       end    
  1267.      
  1268.       -- step 2: build all bases
  1269.       if interiors[interiorID]["base"]~=nil then
  1270.         -- there is a base defined
  1271.         execCommand("setblock",basisX,basisY,basisZ,"minecraft:wool",14,"replace")
  1272.         for ib=1,#interiors[interiorID]["base"],1 do
  1273.           -- one base at a time
  1274.          
  1275.           -- apply probability
  1276.           tmpC=interiors[interiorID]["base"][ib]["chance"]
  1277.           if math.random()<=tmpC or blnAllRndInteriorBases then
  1278.  
  1279.             -- prepare+defaults
  1280.             --tmpBy=interiors[interiorID]["base"][ib]["y"]
  1281.             tmpBy1=interiors[interiorID]["base"][ib]["y1"]
  1282.             tmpBy2=interiors[interiorID]["base"][ib]["y2"]
  1283.             tmpBx1=interiors[interiorID]["base"][ib]["x1"]
  1284.             tmpBx2=interiors[interiorID]["base"][ib]["x2"]
  1285.             tmpBz1=interiors[interiorID]["base"][ib]["z1"]
  1286.             tmpBz2=interiors[interiorID]["base"][ib]["z2"]
  1287.             if tmpBx1==nil then tmpBx1=1 end
  1288.             if tmpBx2==nil then tmpBx2=9 end
  1289.             if tmpBz1==nil then tmpBz1=1 end
  1290.             if tmpBz2==nil then tmpBz2=9 end
  1291.             if tmpBy1==nil then tmpBy1=1 end
  1292.             if tmpBy2==nil then tmpBy2=5 end
  1293.             if interiors[interiorID]["base"][ib]["x"]~=nil then
  1294.               -- if x is provided this overwrites x1 and x2      
  1295.               tmpBx1=interiors[interiorID]["base"][ib]["x"]
  1296.               tmpBx2=tmpBx1
  1297.             end
  1298.             if interiors[interiorID]["base"][ib]["z"]~=nil then
  1299.               -- if z is provided this overwrites z1 and z2      
  1300.               tmpBz1=interiors[interiorID]["base"][ib]["z"]
  1301.               tmpBz2=tmpBz1
  1302.             end
  1303.             if interiors[interiorID]["base"][ib]["y"]~=nil then
  1304.               -- if y is provided this overwrites y1 and y2      
  1305.               tmpBy1=interiors[interiorID]["base"][ib]["y"]
  1306.               tmpBy2=tmpBy1
  1307.             end
  1308.             debugPrint(4,"....base",tmpBx1,tmpBx2,tmpBy1,tmpBy2,tmpBz1,tmpBz2) --4
  1309.          
  1310.             -- build it
  1311.             for ix=basisX+tmpBx1,    basisX+tmpBx2, 1 do
  1312.               for iz=basisZ+tmpBz1,  basisZ+tmpBz2, 1 do   
  1313.                 for iy=basisY+tmpBy1,basisY+tmpBy2, 1 do
  1314.                   if type(interiors[interiorID]["base"][ib]["dmg"])=="table" then
  1315.                     -- dmg has several options, take one
  1316.                     tmpBD=interiors[interiorID]["base"][ib]["dmg"][math.random(1,#interiors[interiorID]["base"][ib]["dmg"])]
  1317.                     debugPrint(4,"...Rnd damage value=",tmpBD)
  1318.                   else
  1319.                     -- take the one and only value 
  1320.                     tmpBD=interiors[interiorID]["base"][ib]["dmg"]
  1321.                   end
  1322.                   execCommand("setblock",ix,iy,iz,interiors[interiorID]["base"][ib]["mat"],tmpBD,"replace")
  1323.                 end            
  1324.               end
  1325.             end        
  1326.           end
  1327.         end
  1328.       else
  1329.         -- leave the standard room material
  1330.       end
  1331.      
  1332.       -- step 3: place all defined blocks
  1333.       if interiors[interiorID]["blocks"]~=nil then
  1334.        
  1335.         for iBlock = 1,#interiors[interiorID]["blocks"],1 do
  1336.           -- apply probability
  1337.           tmpC=interiors[interiorID]["blocks"][iBlock]["chance"]
  1338.           if math.random()<=tmpC or blnAllRndInteriorBlocks then
  1339.             -- prepare data
  1340.             if type(interiors[interiorID]["blocks"][iBlock]["x"])=="table" then
  1341.               -- x has several options, take one
  1342.               tmpX=basisX+interiors[interiorID]["blocks"][iBlock]["x"][math.random(1,#interiors[interiorID]["blocks"][iBlock]["x"])]
  1343.             else
  1344.               -- take the one and only value   
  1345.               tmpX=basisX+interiors[interiorID]["blocks"][iBlock]["x"]
  1346.             end
  1347.             if type(interiors[interiorID]["blocks"][iBlock]["y"])=="table" then
  1348.               -- y has several options, take one
  1349.               tmpY=basisY+interiors[interiorID]["blocks"][iBlock]["y"][math.random(1,#interiors[interiorID]["blocks"][iBlock]["y"])]
  1350.             else
  1351.               -- take the one and only value           
  1352.               tmpY=basisY+interiors[interiorID]["blocks"][iBlock]["y"]
  1353.             end
  1354.             if type(interiors[interiorID]["blocks"][iBlock]["z"])=="table" then
  1355.               -- z has several options, take one
  1356.               tmpZ=basisZ+interiors[interiorID]["blocks"][iBlock]["z"][math.random(1,#interiors[interiorID]["blocks"][iBlock]["z"])]
  1357.             else
  1358.               -- take the one and only value   
  1359.               tmpZ=basisZ+interiors[interiorID]["blocks"][iBlock]["z"]
  1360.             end
  1361.             if type(interiors[interiorID]["blocks"][iBlock]["dmg"])=="table" then
  1362.               -- dmg has several options, take one
  1363.               tmpD=interiors[interiorID]["blocks"][iBlock]["dmg"][math.random(1,#interiors[interiorID]["blocks"][iBlock]["dmg"])]
  1364.               debugPrint(4,"...Rnd damage value=",tmpD)--4
  1365.             else
  1366.               -- take the one and only value   
  1367.               tmpD=interiors[interiorID]["blocks"][iBlock]["dmg"]
  1368.             end
  1369.             if type(interiors[interiorID]["blocks"][iBlock]["mat"])=="table" then
  1370.               -- mat has several options, take one
  1371.               tmpM=interiors[interiorID]["blocks"][iBlock]["mat"][math.random(1,#interiors[interiorID]["blocks"][iBlock]["mat"])]
  1372.               debugPrint(4,"...Rnd mat value=",tmpM)--4
  1373.             else
  1374.               -- take the one and only value   
  1375.               tmpM=interiors[interiorID]["blocks"][iBlock]["mat"]
  1376.             end            
  1377.            
  1378.             --tmpM=interiors[interiorID]["blocks"][iBlock]["mat"]
  1379.             tmpE=interiors[interiorID]["blocks"][iBlock]["extra"]
  1380.             debugPrint(4,"....setBlock",tmpX,tmpY,tmpZ,tmpM,tmpD,"replace") --4
  1381.             if tmpE==nil then  
  1382.               execCommand("setblock",tmpX,tmpY,tmpZ,tmpM,tmpD,"replace")
  1383.             else
  1384. -- no error checks
  1385.               -- there is extra data
  1386.               -- check for absolute coordinates in case
  1387.               if interiors[interiorID]["blocks"][iBlock]["absolute"]~=nil then
  1388.                 -- try to replace ~x ~y ~z with absolute coordinates
  1389.                 debugPrint(1,"Found absolute coordinates in interiorID=",interiorID)--3
  1390.                 --  e.g.: "{Command:/tp @p ~-1 ~1 ~4 }"
  1391.                 --  last coordinate MUST have a space after the number!
  1392.                 tmpE_new_all=tmpE
  1393.                
  1394.                 --[[
  1395.                 -- step a1 are there at least three ~ in tmpE
  1396.                 tmpE_num=string.find(tmpE_new_all,"~")
  1397.                 tmpE_new_all=string.sub
  1398.                 tmpE_new[1]=string.sub(tmpE_new_all,tmpE_num)
  1399.                 tmpE_new[1]=string.sub(tmpE_new[1],1,string.find(tmpE_new[1],"~"))
  1400.                 -- step a2 are they followed by numbers
  1401.                 ]]--
  1402.                
  1403.                 tmpE_new_all,tmpE_new[1]=cutString(tmpE_new_all,"~")
  1404.                 tmpE_new[1], tmpE_new[2]=cutString(tmpE_new[1],"~")
  1405.                 tmpE_new[2], tmpE_new[3]=cutString(tmpE_new[2],"~")
  1406.                 tmpE_new[3], tmpE_new[4]=cutString(tmpE_new[3]," ")
  1407.                
  1408.                 tmpE_new[1]=tonumber(tmpE_new[1])+tmpX
  1409.                 tmpE_new[2]=tonumber(tmpE_new[2])+tmpY
  1410.                 tmpE_new[3]=tonumber(tmpE_new[3])+tmpZ
  1411.                
  1412.                
  1413.                 -- step a3 replace the numbers with absolute coordinates
  1414.                 --[[
  1415. print("."..tmpE..".")
  1416. print("."..tmpE_new_all..".")
  1417. print("."..tmpE_new[1]..".")   
  1418. print("."..tmpE_new[2]..".")
  1419. print("."..tmpE_new[3]..".")
  1420. print("."..tmpE_new[4]..".")
  1421. --askForInputText()
  1422. ]]--   
  1423.                 tmpE=tmpE_new_all..tmpE_new[1].." "..tmpE_new[2].." "..tmpE_new[3]..tmpE_new[4]
  1424. --print("."..tmpE..".")
  1425.               end
  1426.               execCommand("setblock",tmpX,tmpY,tmpZ,tmpM,tmpD,"replace",tmpE)
  1427.             end
  1428.            
  1429.             -- step 3: save chest locations
  1430.             if tmpM=="minecraft:trapped_chest" then
  1431.               if interiors[interiorID]["blocks"][iBlock]["noRandomLoot"]==nil then
  1432.                 -- only if chest isn't marked as noRandomLoot
  1433.                 rooms[xRoom][zRoom]["chest"][#rooms[xRoom][zRoom]["chest"]+1]={tmpX,tmpY,tmpZ,tmpD}
  1434.                 debugPrint(3,"saved chest data:",xRoom,zRoom,#rooms[xRoom][zRoom]["chest"],tmpX,tmpY,tmpZ,tmpD)
  1435.               end
  1436.             end
  1437.           end        
  1438.         end
  1439.       else
  1440.         -- this interior has no defined blocks
  1441.       end
  1442.  
  1443.       -- step 4: recursive call for sub-interiors
  1444.       if interiors[interiorID]["subinterior"]~=nil then
  1445.         -- there is a sub-interior
  1446.        
  1447.         for iSub=1,#interiors[interiorID]["subinterior"],1 do
  1448.          
  1449.           -- array of names?
  1450.           if type(interiors[interiorID]["subinterior"][iSub]["name"])=="table" then
  1451.             -- x has several options, take one
  1452.             tmpSubName=interiors[interiorID]["subinterior"][iSub]["name"][math.random(1,#interiors[interiorID]["subinterior"][iSub]["name"])]
  1453.           else
  1454.             -- take the one and only value 
  1455.             tmpSubName=interiors[interiorID]["subinterior"][iSub]["name"]
  1456.           end
  1457.        
  1458.           debugPrint(2,"..checking sub-interior "..tmpSubName)--2
  1459.           -- apply probability
  1460.           tmpC=interiors[interiorID]["subinterior"][iSub]["chance"]
  1461.           if math.random()<=tmpC or blnAllRndSubinteriors then
  1462.             -- get sub-interior id
  1463.             blnFoundSubinterior=false
  1464.             for iSubId=cRoomInteriorMax+1,#interiors,1 do
  1465.               if tmpSubName==interiors[iSubId]["name"] then
  1466.                 blnFoundSubinterior=true
  1467.                 -- recursive call
  1468.                 implementInterior(xRoom,zRoom,iSubId)
  1469.                 break
  1470.               end
  1471.             end
  1472.             if not blnFoundSubinterior then
  1473.               -- didn't fine the sub-interior
  1474.               debugPrint(0,"..didn't find sub-interior "..tmpSubName)
  1475.             end
  1476.           end      
  1477.         end
  1478.       else
  1479.         -- no sub-interiors
  1480.       end  
  1481.      
  1482.       -- step 5: summon entities
  1483.       if interiors[interiorID]["summon"]~=nil then
  1484.         -- there is a summon entry
  1485.         for iSummon=1,#interiors[interiorID]["summon"],1 do
  1486.           debugPrint(2,"..checking summon "..interiors[interiorID]["summon"][iSummon]["entity"])--2
  1487.           -- apply probability
  1488.           tmpC=interiors[interiorID]["summon"][iSummon]["chance"]
  1489.           if math.random()<=tmpC or blnAllSummons then
  1490.             -- summon that entity
  1491.             -- might be obstructed(!)
  1492.             tmpX=basisX+interiors[interiorID]["summon"][iSummon]["x"]
  1493.             tmpY=basisY+interiors[interiorID]["summon"][iSummon]["y"]
  1494.             tmpZ=basisZ+interiors[interiorID]["summon"][iSummon]["z"]
  1495.             tmpE=interiors[interiorID]["summon"][iSummon]["extra"]
  1496.  
  1497.             execCommand("summon",interiors[interiorID]["summon"][iSummon]["entity"],tmpX,tmpY,tmpZ,tmpE)
  1498.            
  1499.           end      
  1500.         end
  1501.       else
  1502.         -- no entities to summon
  1503.       end
  1504.      
  1505.  
  1506. end
  1507. ---------------------------------------
  1508. local function implementRooms()
  1509.   -- implements the defined rooms
  1510.   debugPrint(1,"implementRooms")
  1511.  
  1512.   -- step 1: implement room interiors
  1513.   for xRoom=1,#rooms,1 do
  1514.     for zRoom=1,#rooms[1],1 do
  1515.       implementInterior(xRoom,zRoom,rooms[xRoom][zRoom]["interior"])
  1516.     end
  1517.   end
  1518.  
  1519.   -- step 2: implement exit mechanism
  1520.   implementInterior(#rooms,exitRoomZ,cRoomInteriorExit)
  1521.   --interiors_addons
  1522.  
  1523. end
  1524. ---------------------------------------
  1525. local function addItemToChest(intChest,intItemId,intItemCount,intItemDmg)
  1526. -- enlarges chests[intChest]["item"] and adds the item and amount
  1527. debugPrint(3,"..adding item to chest "..intChest..":",#chests[intChest]["item"]+1,intItemId,intItemCount,intItemDmg) --3
  1528. --print(#chests[intChest]["item"])
  1529.   local tmpItem=#chests[intChest]["item"]+1
  1530.   if intItemDmg==nil then   intItemDmg=0 end
  1531.   if intItemCount==nil then intItemCount=1 end
  1532.  
  1533.   chests[intChest]["item"][tmpItem]={}
  1534.   chests[intChest]["item"][tmpItem]["id"]   =intItemId
  1535.   chests[intChest]["item"][tmpItem]["count"]=intItemCount
  1536.   chests[intChest]["item"][tmpItem]["dmg"]  =intItemDmg
  1537.  
  1538. --print(chests[intChest]["item"][tmpItem]["count"])
  1539. --os.sleep(1)
  1540. end
  1541. ---------------------------------------
  1542. local function defineGoldDistribution()
  1543. -- distributes the ingpt, nuggets etc. onto the rooms
  1544. -- so far only dependant on lab size
  1545. -- not on level
  1546. debugPrint(1,"defineGoldDistribution") --1
  1547.  
  1548. local intIngots=9
  1549. local intNuggets=0
  1550. local intRoomCount=#rooms*#rooms[1]
  1551. local intRoomsLeft=0
  1552. local intAveragNumberOfNuggets=0
  1553. local intNuggetsRemainder=0
  1554. local tmpFrom =0
  1555. local tmpTo   =0
  1556. local tmpId   =""
  1557. local tmpCount=0
  1558.  
  1559.   -- step 1: get right amount of nuggets
  1560.   while intRoomCount>intIngots+intNuggets do
  1561.     intIngots=intIngots-1
  1562.     intNuggets=intNuggets+9  
  1563.   end
  1564.   debugPrint(0,".."..intRoomCount.." rooms: (ingot,nuggets)=",intIngots,intNuggets) --3
  1565.  
  1566.   -- step 2: distribute them in random order
  1567.   -- step 2.1: gold ingots
  1568.   for i=1,intIngots,1 do
  1569.     goldDistribution[i]={id=cMatId_GoldIngot,count=1}
  1570.   end
  1571.  
  1572.   -- step 2.2: gold nuggets
  1573.   intRoomsLeft=intRoomCount-intIngots
  1574.   intAveragNumberOfNuggets=math.floor(intNuggets/intRoomsLeft)
  1575.   intNuggetsRemainder=intNuggets-intAveragNumberOfNuggets*intRoomsLeft
  1576.  
  1577.   for i=intIngots+1,intRoomCount,1 do
  1578.     goldDistribution[i]={id=cMatId_GoldNugget,count=intAveragNumberOfNuggets}
  1579.     if i==intIngots+1 then goldDistribution[i]["count"]=goldDistribution[i]["count"]+intNuggetsRemainder end  
  1580.   end
  1581.  
  1582.   -- step 3: level adjustments
  1583.   if intLabLevel>=2 and intIngots>0 then
  1584.     -- exchange one ingot with ore (coal is assured in chestItems)
  1585.     goldDistribution[1]["id"]=cMatId_GoldOre
  1586.   end
  1587.  
  1588.  
  1589.   -- step 4: randomize distribution
  1590.   for i=1,intRoomCount,1 do -- start exchange once from each room
  1591.     tmpFrom=i--math.random(1,#goldDistribution)
  1592.     tmpTo  =math.random(1,#goldDistribution)  
  1593.  
  1594.     tmpId   =goldDistribution[tmpFrom]["id"]
  1595.     tmpCount=goldDistribution[tmpFrom]["count"]
  1596.  
  1597.     goldDistribution[tmpFrom]["id"]   =goldDistribution[tmpTo]["id"]
  1598.     goldDistribution[tmpFrom]["count"]=goldDistribution[tmpTo]["count"]
  1599.  
  1600.     goldDistribution[tmpTo]["id"]   =tmpId
  1601.     goldDistribution[tmpTo]["count"]=tmpCount
  1602.     debugPrint(4,"..exchanging goldDistribution:",tmpFrom,tmpTo)--4
  1603.   end
  1604.  
  1605. end
  1606. ---------------------------------------
  1607. local function defineChestItems()
  1608. debugPrint(1,"defineChestItems") --1
  1609. -- fill in chests
  1610.   local tmpX=0
  1611.   local tmpY=0
  1612.   local tmpZ=0
  1613.   local tmpD=0
  1614.   local tmpChest=0
  1615.   local tmpNewChest=0
  1616.   local tmpNewItem=0
  1617.   local tmpBlock={}
  1618.   local tmpItemLevelOk=false
  1619.   local tmpItemProp=0--0.10 --1--
  1620.   local tmpItemCount=0
  1621.   local tmpItemDmg=0
  1622.   local strItems=""
  1623.   local countGoldIndicator=0
  1624.   --[[
  1625.   -- chests[]
  1626. -- chests[i]["x"]/["y"]/["z"] = coordinates
  1627. -- chests[i]["dmg"]           = damage value (direction not working atm)
  1628. -- chests[i]["items"]={}
  1629. --                   [1]["id"]=id to be used in command
  1630. --                   [1]["count"]=counter to be used in command
  1631.  
  1632. local chests ={}
  1633.   ]]--
  1634.  
  1635.   -- step 1: assign gold ingots etc. to each room
  1636.   for ix=1,#rooms,1 do
  1637.     for iz=1,#rooms[1],1 do
  1638.       -- pick chest to put the ingot in
  1639.       if #rooms[ix][iz]["chest"]==0 then
  1640.         debugPrint(0,"ERROR: Probably no chest defined in '"..interiors[rooms[ix][iz]["interior"]]["name"].."'")--0
  1641.       end
  1642.      
  1643.       tmpChest=math.random(1,#rooms[ix][iz]["chest"])
  1644.      
  1645.       -- step 2: create chest array
  1646.       for ic=1,#rooms[ix][iz]["chest"],1 do
  1647.         tmpNewChest=#chests+1
  1648.         chests[tmpNewChest]={}
  1649.         chests[tmpNewChest]["x"]  =rooms[ix][iz]["chest"][ic][1]
  1650.         chests[tmpNewChest]["y"]  =rooms[ix][iz]["chest"][ic][2]
  1651.         chests[tmpNewChest]["z"]  =rooms[ix][iz]["chest"][ic][3]
  1652.         chests[tmpNewChest]["dmg"]=rooms[ix][iz]["chest"][ic][4]
  1653.         chests[tmpNewChest]["fromEntrance"]=rooms[ix][iz]["fromEntrance"]
  1654.         chests[tmpNewChest]["item"]={}
  1655.        
  1656.         -- ingot
  1657.         if tmpChest==ic then
  1658.           countGoldIndicator=countGoldIndicator+1
  1659.           addItemToChest(tmpNewChest,goldDistribution[countGoldIndicator]["id"],goldDistribution[countGoldIndicator]["count"])
  1660.         end
  1661.  
  1662.       end
  1663.     end
  1664.   end
  1665.  
  1666.   --[[
  1667.    -- step 3: some random test loot  
  1668.   for ic=1,#chests,1 do
  1669.     -- poppy
  1670.     if math.random()<=tmpItemProp then addItemToChest(ic, 38,1) end
  1671.     -- carrot
  1672.     if math.random()<=tmpItemProp then addItemToChest(ic,391,1) end
  1673.     -- stone sword
  1674.     if math.random()<=tmpItemProp then addItemToChest(ic,272,1) end
  1675.  
  1676.   end
  1677.   ]]--
  1678.  
  1679.   -- step 3: apply chestItems for randomized level loot
  1680.   for iI=1,#chestItems,1 do
  1681.     -- check for correct level (single value or array) 
  1682.     tmpItemLevelOk=false --default
  1683.     if type(chestItems[iI]["level"])=="table" then
  1684.       for iLevel=1,#chestItems[iI]["level"],1 do
  1685.         if chestItems[iI]["level"][iLevel]==intLabLevel then tmpItemLevelOk=true break end
  1686.       end
  1687.     else
  1688.       -- single value
  1689.       if chestItems[iI]["level"]==intLabLevel then tmpItemLevelOk=true end
  1690.     end
  1691.  
  1692.     if tmpItemLevelOk then --chestItems[iI]["level"]==intLabLevel then
  1693.       -- right level of item
  1694.       if math.random()<=chestItems[iI]["chance"] then
  1695.         -- okay, put loot randomly in chest
  1696.        
  1697.         -- check for multiple count values
  1698.         if type(chestItems[iI]["count"])=="table" then
  1699.           -- item count has several options, take one
  1700.           tmpItemCount=chestItems[iI]["count"][math.random(1,#chestItems[iI]["count"])]
  1701.         else
  1702.           -- take the one and only value           
  1703.           tmpItemCount=chestItems[iI]["count"]
  1704.         end
  1705.        
  1706.         -- check for multiple dmg values
  1707.         if type(chestItems[iI]["dmg"])=="table" then
  1708.           -- item dmg has several options, take one
  1709.           tmpItemDmg=chestItems[iI]["dmg"][math.random(1,#chestItems[iI]["dmg"])]
  1710.         else
  1711.           -- take the one and only value           
  1712.           tmpItemDmg=chestItems[iI]["dmg"]
  1713.         end
  1714.        
  1715.         -- add it
  1716.         addItemToChest(math.random(1,#chests),chestItems[iI]["id"],tmpItemCount,tmpItemDmg)
  1717.        
  1718.       end
  1719.     end
  1720.     --chestItems[1]={level=1,chance=0.5,id= 38,dmg=0,count=1} --poppy
  1721.  
  1722.  
  1723.  
  1724.   end
  1725.  
  1726.  
  1727.   -- step x: trap some chests  
  1728.   for ic=1,#chests,1 do
  1729.       tmpX=chests[ic]["x"]
  1730.       tmpY=chests[ic]["y"]
  1731.       tmpZ=chests[ic]["z"]
  1732.       tmpD=chests[ic]["dmg"]
  1733.     if (tmpY==yHome+cOffsetY+1 or tmpY==yHome+cOffsetY or tmpY==yHome+cOffsetY-1) and math.random()<= cTrapProbability then
  1734.       -- trap it     
  1735.       debugPrint(3,"  .. trapped chest "..ic.." :D") --3
  1736.      
  1737.       -- step x.1: set-up redstone impulse
  1738.       execCommand("setblock",tmpX,tmpY-2,tmpZ,"minecraft:command_block","0","replace","{Command:/setblock ~0 ~-1 ~0 minecraft:redstone_block 0 replace}")
  1739.       execCommand("setblock",tmpX,tmpY-4,tmpZ,"minecraft:command_block","0","keep","{Command:/setblock ~0 ~1 ~0 minecraft:air 0 replace}")
  1740.      
  1741.       -- step x.2: level 1+ mobs
  1742.       if math.random()>=0.5 then
  1743.         -- Zombie
  1744.         execCommand("setblock",tmpX,tmpY-3,tmpZ-1,"minecraft:command_block","0","keep","{Command:/summon Zombie ~0 ~5 ~1 {Equipment:[{},{},{},{},{id:298}]}}")
  1745.       else
  1746.         -- Skeleton
  1747.         execCommand("setblock",tmpX,tmpY-3,tmpZ-1,"minecraft:command_block","0","keep","{Command:/summon Skeleton ~0 ~5 ~1 {Equipment:[{id:271},{},{},{},{Count:1,id:298}],DropChances:[0.0F,0.0F,0.0F,0.0F,0.1F]}}")
  1748.       end    
  1749.      
  1750.       -- step x.3: level 3+ mobs
  1751.       if intLabLevel>=3 then
  1752.         if math.random()>=0.5 then
  1753.           -- bonus slime
  1754.           execCommand("setblock",tmpX-1,tmpY-3,tmpZ,"minecraft:command_block","0","keep","{Command:/summon Slime ~1 ~5 ~0}")
  1755.         end
  1756.       end    
  1757.      
  1758.       -- ensure there is a block to transmit the rs signal
  1759.       execCommand("setblock",tmpX,tmpY-1,tmpZ,"minecraft:stone","0","keep")
  1760.     end  
  1761.   end
  1762.  
  1763. end
  1764. ---------------------------------------
  1765. local function defineKeyItemDistribution()
  1766. -- checks for need of certain key items and distributes them accordingly
  1767. -- so far: 1) flint and steel for sand-TNT
  1768. --         2) disc far for jukebox
  1769. debugPrint(0,"defineKeyItemDistribution") --1
  1770.   local tmpGo=false
  1771.   local tmpDistance=0
  1772.   local tmpChest=0
  1773.   local tmpCount=0
  1774.  
  1775.   -- step 1: flint and steel for sand-TNT
  1776.   -- step 1.1: sand-TNT in game?
  1777.   for xRoom=1,#rooms,1 do
  1778.     for zRoom=1,#rooms[1],1 do
  1779.       if interiors[rooms[xRoom][zRoom]["interior"]]["name"]=="sand-TNT" then
  1780.         tmpGo=true
  1781.         tmpDistance=rooms[xRoom][zRoom]["fromEntrance"]
  1782.         break
  1783.       end
  1784.     end
  1785.   end
  1786.  
  1787.   if tmpGo then
  1788.     -- step 1.2: find chest for flint and steel
  1789.     tmpCount=0
  1790.     repeat
  1791.       tmpChest=math.random(1,#chests)
  1792.       tmpCount=tmpCount+1  
  1793.     until chests[tmpChest]["fromEntrance"]<tmpDistance
  1794.  
  1795.     -- step 1.3: add item
  1796.     addItemToChest(tmpChest,cMatId_FlintAndSteel,1,64)
  1797.     debugPrint(2,"Keys: added flint&steel after "..tmpCount.." tries to chest "..tmpChest)--2
  1798.   else
  1799.     debugPrint(2,"Keys: no sand-TNT, no flint&steel")--2
  1800.   end
  1801.  
  1802.   -- step 2: disc for jukebox
  1803.   tmpGo=false
  1804.   tmpDistance=0
  1805.   tmpChest=0
  1806.   tmpCount=0
  1807.   -- step 2.1: jukebox in game?
  1808.   for xRoom=1,#rooms,1 do
  1809.     for zRoom=1,#rooms[1],1 do
  1810.       if interiors[rooms[xRoom][zRoom]["interior"]]["name"]=="jukebox" then
  1811.         tmpGo=true
  1812.         tmpDistance=rooms[xRoom][zRoom]["fromEntrance"]
  1813.         break
  1814.       end
  1815.     end
  1816.   end
  1817.  
  1818.   if tmpGo then
  1819.     -- step 2.2: find chest for disc
  1820.     tmpCount=0
  1821.     repeat
  1822.       tmpChest=math.random(1,#chests)
  1823.       tmpCount=tmpCount+1  
  1824.     until chests[tmpChest]["fromEntrance"]<tmpDistance
  1825.  
  1826.     -- step 2.3: add item
  1827.     addItemToChest(tmpChest,cMatId_DiscFar,1,64)
  1828.     debugPrint(2,"Keys: added disc far after "..tmpCount.." tries to chest "..tmpChest)--2
  1829.   else
  1830.     debugPrint(2,"Keys: no jukebox, no discs")--2
  1831.   end
  1832. end
  1833. ---------------------------------------
  1834. local function implementChestItems()
  1835. debugPrint(1,"implementChestItems") --1
  1836. -- fill in chests
  1837.   local tmpX=0
  1838.   local tmpY=0
  1839.   local tmpZ=0
  1840.   local tmpD=0
  1841.  
  1842.  
  1843.  
  1844.   -- step 1: set chests again with the items
  1845.     for ic=1,#chests,1 do
  1846. --print("here",ic," ",#chests)
  1847.       tmpX=chests[ic]["x"]
  1848.       tmpY=chests[ic]["y"]
  1849.       tmpZ=chests[ic]["z"]
  1850.       tmpD=chests[ic]["dmg"]
  1851.     if #chests[ic]["item"]>0 then
  1852.       -- there are items to place in the chest
  1853.       strItems=""
  1854.      
  1855.       -- tmp only first
  1856.       -- tmp no rnd slot numbers
  1857. --print(chests[ic]["item"][1])   
  1858.       for iItem=1,#chests[ic]["item"],1 do
  1859.         -- build string for chest items
  1860.         if iItem>1 then strItems=strItems.."," end
  1861. --write(chests[ic]["item"][iItem]["count"])
  1862.         strItems=strItems.."{id:"..tostring(chests[ic]["item"][iItem]["id"])..",Slot:"..tostring(iItem-1)..",Count:"..tostring(chests[ic]["item"][iItem]["count"])..",Damage:"..tostring(chests[ic]["item"][iItem]["dmg"]).."}"
  1863.          
  1864.       end
  1865.       debugPrint(4,"..",strItems) --4
  1866.       execCommand("setblock",tmpX,tmpY,tmpZ,"minecraft:trapped_chest",0,"replace","{Items:["..strItems.."]}")
  1867.       -- info: {Items:[:{Count:1,Slot:0,id:35,Damage:1}]}
  1868.       -- info: {Items:[{id:276,Slot:1,Count:1},{id:277,Slot:Β­0,Count:2}]}
  1869. --print(ic,": ",tmpX,tmpY,tmpZ,tmpD)
  1870.     --"{Items:[{id:"..cMatId_WoodenSword..",Slot:1,Count:1]}}"  
  1871.     end  
  1872.   end
  1873. end
  1874. ---------------------------------------
  1875.  
  1876.  
  1877. ------------------------------------------------------------------------------
  1878. ---- MAIN --------------------------------------------------------------------
  1879. ------------------------------------------------------------------------------
  1880. debugPrint(0,"Base coordinates = ",xHome+cOffsetX,yHome+cOffsetY,zHome+cOffsetZ)--1
  1881. debugPrint(0,"Room grid = ",#rooms,#rooms[1])--2
  1882. debugPrint(0,"Door grid = ",#doors,#doors[1])--2
  1883. debugPrint(0,"Level = ",intLabLevel)--2
  1884.  
  1885. ------------------------------------------------------------------------------
  1886. -- reset rooms ---------------------------------------------------------------
  1887.   -- walls, floor, air blocks, underground
  1888.   resetRooms()--xHome+cOffsetX,yHome+cOffsetY,zHome+cOffsetZ)
  1889.   if blnJustClear then return end
  1890.  
  1891. ------------------------------------------------------------------------------
  1892. -- get door distribution -----------------------------------------------------
  1893.   -- which rooms are connected
  1894.   -- ensure all rooms are accessible
  1895.   -- idea: include underground paths
  1896.   defineDoors()
  1897.  
  1898. ------------------------------------------------------------------------------
  1899. -- implement doors -----------------------------------------------------------
  1900.   -- idea: choose variants for room connections (e.g., door on left, right, double,...)
  1901.   -- idea: implement doors and block reserved floor space
  1902.   -- idea: choose underground path type
  1903.   -- idea: implement underground paths and block reserved floor space
  1904. --implementDoors() => moved to end to give not early access to players
  1905.  
  1906. ------------------------------------------------------------------------------
  1907. -- get room assignment -------------------------------------------------------
  1908.   -- idea: should this be dependant on room distance ? => later
  1909.   -- assign entry room
  1910.   -- idea: check for multi-room constructions
  1911.   -- idea: choose and balance room type assignments
  1912.   -- idea: including chests (rooms[ix][iz]["chest"])
  1913.   defineRooms()
  1914.  
  1915. ------------------------------------------------------------------------------
  1916. -- implement rooms -----------------------------------------------------------
  1917.   -- select from different variants available
  1918.   -- idea: implement rooms considering reserved floor blocks => atm via design
  1919.   implementRooms()  
  1920.  
  1921. ------------------------------------------------------------------------------
  1922. -- ensure door accessibility -------------------------------------------------  
  1923.   -- idea: delete blocking blocks
  1924.   -- hm, for now I ensure that there are no blocks (and door pos is fixed)
  1925.  
  1926. ------------------------------------------------------------------------------
  1927. -- define and implement chests -----------------------------------------------
  1928.   -- idea: starter chest in rooms near to entrance
  1929.   -- chests due to room chest likely-hood
  1930.   -- basic supplies
  1931.   -- random loot
  1932.   -- difficulty dependant loot
  1933.   -- labyrinth relevant loot (dependant on certain interior types)
  1934.   -- trap some chests with mob spawning
  1935.   -- idea: add a do-not-trap attribute to interior chests
  1936.   defineGoldDistribution()
  1937.   defineChestItems()
  1938.   defineKeyItemDistribution()
  1939.   implementChestItems()
  1940.  
  1941. ------------------------------------------------------------------------------
  1942. -- populate rooms ------------------------------------------------------------
  1943.   -- idea: animals
  1944.   -- mobs
  1945.   -- idea: despawnable items
  1946. -- atm done with interiors, not sure if I want this or not  
  1947.  
  1948. -------------------------------------------------------------------------------
  1949. -- allow access ---------------------------------------------------------------
  1950.   implementDoors()  -- allow access only at end of construction process
  1951.  
  1952.  
  1953. -------------------------------------------------------------------------------
  1954. -------------------------------------------------------------------------------
  1955.   if #tArgs >= 7 then
  1956. --if finalCommand~="" then
  1957.     execCommand("say Builder up to do: "..finalCommand)
  1958.     --os.sleep(1)
  1959.     execCommand(finalCommand)  --e.g. set signals
  1960.     execCommand("say Builder: done "..cRoomsGridX.."x"..cRoomsGridZ)
  1961.     --[[
  1962.     commands.execAsync("say up to do: "..finalCommand)
  1963.     commands.execAsync(finalCommand)  --e.g. set signals
  1964.     commands.execAsync("say done!")
  1965.     ]]--
  1966.   end
  1967.   if blnDebug then print("Builder: done ",cRoomsGridX,"x",cRoomsGridZ) end
  1968. -------------------------------------------------------------------------------
Add Comment
Please, Sign In to add comment