Krutoy242

KrutoyTurtle (stable version)

May 16th, 2014
529
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- ********************************************************************************** --
  2. -- **                                                                              ** --
  3. -- **   Krutoy Turtle   (stable version)                                           ** --
  4. -- **   ----------------------------------------------------                       ** --
  5. -- **                                                                              ** --
  6. -- **   To start program, write in turte:                                          ** --
  7. -- **                                                                              ** --
  8. -- **    For stable version:                                                       ** --
  9. -- **   pastebin get YxWNp5bZ KrutoyTurtle                                         ** --
  10. -- **                                                                              ** --
  11. -- **    For developing version                                                    ** --
  12. -- **   pastebin get GHUv2MCR KrutoyTurtle                                         ** --
  13. -- **                                                                              ** --
  14. -- **   ----------------------------------------------------                       ** --
  15. -- **   Thanks for this peoples, i use theirs code:                                ** --
  16. -- **    - AustinKK (OreQuarry Turtle)                                             ** --
  17. -- **    - NitrogenFingers (NPaintPro)                                             ** --
  18. -- **   ----------------------------------------------------                       ** --
  19. -- **                                                                              ** --
  20. -- **                                                                              ** --
  21. -- ********************************************************************************** --
  22.  
  23. ------------------------------------------------------
  24. -- Filling function variables                       --
  25. ------------------------------------------------------
  26.  
  27. -- Main patterns, using in fill() function
  28. --  Numbers tell what the count block will be placed
  29. --  Exists: fillPattern[name][z][y][x]
  30. --  [space]: here will no block
  31. --  0: remove block here
  32. fillPattern = {
  33.   ['Plain'] =
  34.   { {'1'} },
  35.   ['BoxGrid'] =
  36.    {{'3222';
  37.      '2111';
  38.      '2111';
  39.      '2111';},
  40.     {'2111';
  41.      '1   ';
  42.      '1   ';
  43.      '1   ';},
  44.     {'2111';
  45.      '1   ';
  46.      '1   ';
  47.      '1   ';},
  48.     {'2111';
  49.      '1   ';
  50.      '1   ';
  51.      '1   ';}}
  52. }
  53.  
  54.  
  55. fillingFlags = {
  56.   'sides',          -- Making boxes without corners
  57.   'corners',        -- Making frames
  58.   'mirror',         -- Pattern texture will mirrored
  59.   'mirror -1',      -- Each mirrored pattern indexes will shif by one block
  60.   'mirror -1x',
  61.   'mirror -1y',
  62.   'mirror -1z',
  63.   'y->',            -- Build first x-z blocks, then go to next y layer
  64.   'x++', 'x--',     -- Shift next coord. Userful for stairs
  65.   'y++', 'y--',
  66.   'z++', 'z--',
  67.   'clear',          -- Replaces all pattern indexes to -1
  68.   'clearAllSkipped',-- Replaces all 0 to -1
  69.   'skipClearing',   -- Replaces all -1 to 0
  70.   'tunnel', 'tube'  -- tunnel without caps on start end end
  71. }
  72.  
  73.  
  74. ------------------------------------------------------
  75. -- Other variables                                  --
  76. ------------------------------------------------------
  77.  
  78. --A list of hexidecimal conversions from numbers to hex digits
  79. local hexnums = { [10] = "a", [11] = "b", [12] = "c", [13] = "d", [14] = "e" , [15] = "f" }
  80.  
  81. -- Enumeration to store the the different types of message that can be written
  82. messageLevel = { DEBUG=0, INFO=1, WARNING=2, ERROR=3, FATAL=4 }
  83.  
  84. -- Enumeration to store names for the 6 directions
  85. way = { FORWARD=0, RIGHT=1, BACK=2, LEFT=3, UP=4, DOWN=5 }
  86.  
  87. -- Enumeration of mining states
  88. miningState = { START=0, LAYER=1, EMPTYCHESTDOWN=2, EMPTYINVENTORY=3 }
  89.  
  90. local maximumGravelStackSupported = 25 -- The number of stacked gravel or sand blocks supported
  91. local turtleId -- For rednet
  92. local isWirelessTurtle
  93. local lastMoveNeededDig = true -- Determines whether the last move needed a dig first
  94. local logFileName = "KrutoyTurtle.log"
  95.  
  96. -- Variables to store the current location and orientation of the turtle. x is right, left, z is up, down and
  97. -- y is forward, back with relation to the starting orientation.
  98. local currOrient = way.FORWARD
  99. local currMiningState = miningState.START
  100. local currPos = vector.new() -- Start Pos is 0,0,0
  101.  
  102.  
  103. -- ********************************************************************************** --
  104. -- **                                                                              ** --
  105. -- **                                                                              ** --
  106. -- **                                                                              ** --
  107. -- **                                                                              ** --
  108. -- **                                                                              ** --
  109. -- **                                Utilities                                     ** --
  110. -- **                                                                              ** --
  111. -- **                                                                              ** --
  112. -- **                                                                              ** --
  113. -- **                                                                              ** --
  114. -- **                                                                              ** --
  115. -- ********************************************************************************** --
  116.  
  117. --===========================================================
  118. -- Make keys from values
  119. --===========================================================
  120. function makeSet (list)
  121.   local set = {}
  122.   for _, l in ipairs(list) do set[l] = true end
  123.   return set
  124. end
  125.  
  126. --===========================================================
  127. -- Clear screen and set cursor to start
  128. --===========================================================
  129. function clear()
  130.    term.clear()
  131.    term.setCursorPos (1,1)
  132. end
  133.  
  134.  
  135. --===========================================================
  136. -- Waiting untill user press key
  137. --===========================================================
  138. function pressAnyKey()
  139.   local event, param1 = os.pullEvent ("key")
  140. end
  141.  
  142. --===========================================================
  143. -- Writes requestText and wait while user press number key
  144. --===========================================================
  145. function readNumberParametr(requestText, from, to)
  146.   while true do
  147.      clear()
  148.      print (requestText)
  149.      local event, param1 = os.pullEvent ("char") -- limit os.pullEvent to the char event
  150.      local result = tonumber(param1)
  151.      if type(result) == 'number' and result >= from and result <= to then
  152.          return result
  153.      end
  154.   end
  155. end
  156.  
  157. --===========================================================
  158. -- Writes requestText and wait while user type
  159. -- several words or numbers
  160. --===========================================================
  161. function readTable(requestText, canBeSkipped, separator)
  162.   local resultStr = ''
  163.  
  164.   while true do
  165.     clear()
  166.     print(requestText)
  167.     resultStr = read()
  168.     if resultStr == '' and canBeSkipped == true then
  169.       return nil
  170.     elseif resultStr ~= '' then
  171.       local result = {}
  172.       local i=1
  173.       for v in string.gmatch(resultStr, separator) do
  174.         result[i] = v
  175.         i = i+1
  176.       end
  177.       return result
  178.     end
  179.   end
  180. end
  181.  
  182. --===========================================================
  183. -- Writes requestText and wait while user type
  184. -- several numbers
  185. --===========================================================
  186. function readTableOfNumbers(requestText, canBeSkipped, numbersCount, separator)
  187.   local resultStr = ''
  188.   local result = {}
  189.   for i=1,numbersCount do result[i]=0 end
  190.  
  191.  
  192.   while true do
  193.     local returnedResult = readTable(requestText, canBeSkipped, separator)
  194.    
  195.     if not returnedResult and canBeSkipped == true then
  196.       return result
  197.     elseif(returnedResult)then
  198.       local isAllNumbers = true
  199.       for i=1,numbersCount do
  200.         if(type(tonumber(returnedResult[i])) == "number") then
  201.           result[i] = tonumber(returnedResult[i])
  202.         else
  203.           print(returnedResult[i]..' is not number!')
  204.           sleep(1)
  205.           isAllNumbers=false
  206.         end
  207.       end
  208.      
  209.       if isAllNumbers == true then
  210.         return result
  211.       end
  212.     end
  213.   end
  214. end
  215.  
  216. --===========================================================
  217. -- Writes an output message
  218. -- Also, working with rednet
  219. --===========================================================
  220. function writeMessage(message, msgLevel)
  221.   print(message)
  222.  
  223.   -- If this turtle has a modem, then write the message to red net
  224.   if (isWirelessTurtle == true) then
  225.     if (turtleId == nil) then
  226.       rednet.broadcast(message)
  227.     else
  228.       -- Broadcast the message (prefixed with the turtle's id)
  229.       rednet.broadcast("[".. turtleId.."] "..message)
  230.       end
  231.     end
  232.  
  233.     if (logFileName ~= nil) then
  234.       -- Open file, write message and close file (flush doesn't seem to work!)
  235.     local outputFile
  236.     if (fs.exists(logFileName) == true) then
  237.       outputFile = io.open(logFileName, "a")
  238.     else
  239.       outputFile = io.open(logFileName, "w")
  240.     end
  241.  
  242.     outputFile:write(message)
  243.     outputFile:write("\n")
  244.     outputFile:close()
  245.   end
  246. end
  247.  
  248.  
  249. --===========================================================
  250. -- Reads the next number from a given file
  251. --===========================================================
  252. function readNumber(inputFile)
  253.  
  254.   local returnVal
  255.   local nextLine = inputFile.readLine()
  256.   if (nextLine ~= nil) then
  257.     returnVal = tonumber(nextLine)
  258.   end
  259.  
  260.   return returnVal
  261. end
  262.  
  263. --===========================================================
  264. -- Reads the next number from a given file
  265. --===========================================================
  266. function getChar(str, pos)
  267.   return string.sub(str, pos, pos)
  268. end
  269.  
  270.  
  271. --===========================================================
  272. -- Converts a hex digit into a colour value
  273. -- Params: hex:?string = the hex digit to be converted
  274. -- Returns:string A colour value corresponding to the hex, or nil if the character is invalid
  275. --===========================================================
  276. function getColourOf(hex)
  277.   local value = tonumber(hex, 16)
  278.   if not value then return nil end
  279.   value = math.pow(2,value)
  280.   return value
  281. end
  282.  
  283.  
  284. --===========================================================
  285. -- Converts a colour parameter into a single-digit hex coordinate for the colour
  286. -- Params: colour:int = The colour to be converted
  287. -- Returns:string A string conversion of the colour
  288. --===========================================================
  289. local function getHexOf(colour)
  290.   if not colour or not tonumber(colour) then
  291.     return " "
  292.   end
  293.   local value = math.log(colour)/math.log(2)
  294.   if value > 9 then
  295.     value = hexnums[value]
  296.   end
  297.   return value
  298. end
  299.  
  300.  
  301. --===========================================================
  302. -- Params: path:string = The path in which the file is located
  303. -- Returns:nil
  304. --===========================================================
  305. local function loadNFA(path)
  306.   if fs.exists(path) == false then
  307.     return nil
  308.   end
  309.  
  310.   local frames = { }
  311.   frames[1] = { }
  312.  
  313.   local file = io.open(path, "r" )
  314.   local sLine = file:read()
  315.   local z = 1
  316.   local y = 1
  317.   while sLine do
  318.     if sLine == "~" then
  319.       z = z + 1
  320.       frames[z] = { }
  321.       y = 1
  322.     else
  323.       if not frames[z][y] then frames[z][y]='' end
  324.       for i=1,#sLine do
  325.         frames[z][y] = frames[z][y] .. string.sub(sLine,i,i)
  326.       end
  327.       y = y+1
  328.     end
  329.     sLine = file:read()
  330.   end
  331.   file:close()
  332.  
  333.   return frames
  334. end
  335.  
  336.  
  337. -- ********************************************************************************** --
  338. -- **                                                                              ** --
  339. -- **                                                                              ** --
  340. -- **                                                                              ** --
  341. -- **                                                                              ** --
  342. -- **                                                                              ** --
  343. -- **                            Turtle wrappers                                   ** --
  344. -- **                                                                              ** --
  345. -- **                                                                              ** --
  346. -- **                                                                              ** --
  347. -- **                                                                              ** --
  348. -- **                                                                              ** --
  349. -- ********************************************************************************** --
  350.  
  351.  
  352. -- ********************************************************************************** --
  353. -- Turns the turtle (updating the current orientation at the same time)
  354. -- ********************************************************************************** --
  355. function turtleTurn(turnDir)
  356.  
  357.   if (turnDir == way.LEFT) then
  358.     if (currOrient == way.FORWARD) then
  359.       currOrient = way.LEFT
  360.     elseif (currOrient == way.LEFT) then
  361.       currOrient = way.BACK
  362.     elseif (currOrient == way.BACK) then
  363.       currOrient = way.RIGHT
  364.     elseif (currOrient == way.RIGHT) then
  365.       currOrient = way.FORWARD
  366.     else
  367.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  368.     end
  369.  
  370.  
  371.     -- Write the new orientation and turn
  372.     saveLocation()
  373.     turtle.turnLeft()
  374.  
  375.   elseif (turnDir == way.RIGHT) then
  376.     if (currOrient == way.FORWARD) then
  377.       currOrient = way.RIGHT
  378.     elseif (currOrient == way.LEFT) then
  379.       currOrient = way.FORWARD
  380.     elseif (currOrient == way.BACK) then
  381.       currOrient = way.LEFT
  382.     elseif (currOrient == way.RIGHT) then
  383.       currOrient = way.BACK
  384.     else
  385.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  386.     end
  387.  
  388.  
  389.     -- Write the new orientation and turn
  390.     saveLocation()
  391.     turtle.turnRight()
  392.   else
  393.     writeMessage ("Invalid turnDir in turtleTurn function", messageLevel.ERROR)
  394.   end
  395. end
  396.  
  397. -- ********************************************************************************** --
  398. -- Sets the turtle to a specific orientation, irrespective of its current orientation
  399. -- ********************************************************************************** --
  400. function turtleSetOrientation(newOrient)
  401.  
  402.   -- Already turned
  403.   if (currOrient == newOrient) then return true end
  404.  
  405.  
  406.   -- Wrong parameters - we cant turn up or down
  407.   if newOrient < 0 or newOrient > way.LEFT then
  408.     writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.DEBUG)
  409.     return false
  410.   end
  411.  
  412.   local turn = currOrient - newOrient
  413.   local turnFnc
  414.  
  415.   if turn==1 or turn==-3 then
  416.     turnFnc = turtle.turnLeft
  417.   else
  418.     turnFnc = turtle.turnRight
  419.   end
  420.  
  421.   turn = math.abs(turn)
  422.   if(turn==3) then turn=1 end
  423.  
  424.   currOrient = newOrient
  425.  
  426.  
  427.   for i=1, turn do
  428.     turnFnc()
  429.   end
  430.  
  431. end
  432.  
  433. --===========================================================
  434. -- Dig, depending on direction
  435. --===========================================================
  436. function turtleDig(direction)
  437.   if (direction == nil) or (direction == way.FORWARD) then
  438.     return turtle.dig()
  439.   elseif(direction == way.DOWN) then
  440.     return turtle.digDown()
  441.   elseif(direction == way.UP) then
  442.     return turtle.digUp()
  443.   else
  444.     writeMessage('Wrong direction for turtleDig()', messageLevel.ERROR)
  445.     return false
  446.   end
  447. end
  448.  
  449. -- ********************************************************************************** --
  450. -- Generic function to move the Turtle (pushing through any gravel or other
  451. -- things such as mobs that might get in the way).
  452. --
  453. -- The only thing that should stop the turtle moving is bedrock. Where this is
  454. -- found, the function will return after 15 seconds returning false
  455. -- ********************************************************************************** --
  456. function moveTurtle(moveFn, detectFn, digFn, attackFn, compareFn, suckFn, maxDigCount, newX, newY, newZ)
  457.  
  458.   local moveSuccess = false
  459.  
  460.  
  461.   local prevX, prevY, prevZ
  462.   prevX = currPos.x
  463.   prevY = currPos.y
  464.   prevZ = currPos.z
  465.  
  466.  
  467.   -- Flag to determine whether digging has been tried yet. If it has
  468.   -- then pause briefly before digging again to allow sand or gravel to
  469.   -- drop
  470.   local digCount = 0
  471.  
  472.     if (lastMoveNeededDig == false) then
  473.       -- Didn't need to dig last time the turtle moved, so try moving first
  474.  
  475.       currPos.x = newX
  476.       currPos.y = newY
  477.       currPos.z = newZ
  478.  
  479.       moveSuccess = moveFn()
  480.  
  481.       -- If move failed, update the co-ords back to the previous co-ords
  482.       if (moveSuccess == false) then
  483.         currPos.x = prevX
  484.         currPos.y = prevY
  485.         currPos.z = prevZ
  486.       end
  487.  
  488.       -- Don't need to set the last move needed dig. It is already false, if
  489.       -- move success is now true, then it won't be changed
  490.     else
  491.       -- Try to dig (without doing a detect as it is quicker)
  492.       local digSuccess = digFn()
  493.       if (digSuccess == true) then
  494.         digCount = 1
  495.       end
  496.  
  497.       currPos.x = newX
  498.       currPos.y = newY
  499.       currPos.z = newZ
  500.  
  501.       moveSuccess = moveFn()
  502.  
  503.       if (moveSuccess == true) then
  504.         lastMoveNeededDig = digSuccess
  505.       else
  506.         currPos.x = prevX
  507.         currPos.y = prevY
  508.         currPos.z = prevZ
  509.       end
  510.  
  511.     end
  512.  
  513.     -- Loop until we've successfully moved
  514.     if (moveSuccess == false) then
  515.       while ((moveSuccess == false) and (digCount < maxDigCount)) do
  516.  
  517.         -- If there is a block in front, dig it
  518.         if (detectFn() == true) then
  519.        
  520.             -- If we've already tried digging, then pause before digging again to let
  521.             -- any sand or gravel drop, otherwise check for a chest before digging
  522.             if(digCount == 0) then
  523.            
  524.             else
  525.               sleep(0.1)
  526.             end
  527.  
  528.             digFn()
  529.             digCount = digCount + 1
  530.         else
  531.            -- Am being stopped from moving by a mob, attack it
  532.            attackFn()
  533.         end
  534.  
  535.         currPos.x = newX
  536.         currPos.y = newY
  537.         currPos.z = newZ
  538.  
  539.         -- Try the move again
  540.         moveSuccess = moveFn()
  541.  
  542.         if (moveSuccess == false) then
  543.           currPos.x = prevX
  544.           currPos.y = prevY
  545.           currPos.z = prevZ
  546.         end
  547.       end
  548.  
  549.       if (digCount == 0) then
  550.         lastMoveNeededDig = false
  551.       else
  552.         lastMoveNeededDig = true
  553.       end
  554.     end
  555.  
  556.   -- Return the move success
  557.   return moveSuccess
  558. end
  559.  
  560. -- ********************************************************************************** --
  561. -- Move the turtle forward one block (updating the turtle's position)
  562. -- ********************************************************************************** --
  563. function turtleForward()
  564.  
  565.   -- Determine the new co-ordinate that the turtle will be moving to
  566.   local newX, newY
  567.  
  568.   -- Update the current co-ordinates
  569.   if (currOrient == way.FORWARD) then
  570.     newY = currPos.y + 1
  571.     newX = currPos.x
  572.   elseif (currOrient == way.LEFT) then
  573.     newX = currPos.x - 1
  574.     newY = currPos.y
  575.   elseif (currOrient == way.BACK) then
  576.     newY = currPos.y - 1
  577.     newX = currPos.x
  578.   elseif (currOrient == way.RIGHT) then
  579.     newX = currPos.x + 1
  580.     newY = currPos.y
  581.   else
  582.     writeMessage ("Invalid currOrient in turtleForward function", messageLevel.ERROR)
  583.   end
  584.  
  585.   local returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.compare, turtle.suck, maximumGravelStackSupported, newX, newY, currPos.z)
  586.  
  587.  
  588.   return returnVal
  589. end
  590.  
  591. -- ********************************************************************************** --
  592. -- Move the turtle up one block (updating the turtle's position)
  593. -- ********************************************************************************** --
  594. function turtleUp()
  595.  
  596.   local returnVal = moveTurtle(turtle.up, turtle.detectUp, turtle.digUp, turtle.attackUp, turtle.compareUp, turtle.suckUp, maximumGravelStackSupported, currPos.x, currPos.y, currPos.z + 1)
  597.  
  598.   return returnVal
  599. end
  600.  
  601. -- ********************************************************************************** --
  602. -- Move the turtle down one block (updating the turtle's position)
  603. -- ********************************************************************************** --
  604. function turtleDown()
  605.  
  606.   local returnVal = moveTurtle(turtle.down, turtle.detectDown, turtle.digDown, turtle.attackDown, turtle.compareDown, turtle.suckDown, 1, currPos.x, currPos.y, currPos.z - 1)
  607.  
  608.   return returnVal
  609. end
  610.  
  611. -- ********************************************************************************** --
  612. -- Move the turtle back one block (updating the turtle's position)
  613. -- ********************************************************************************** --
  614. function turtleBack(doNotTurnBack)
  615.  
  616.   -- Assume that the turtle will move, and switch the co-ords back if it doesn't
  617.   -- (do this so that we can write the co-ords to a file before moving)
  618.   local newX, newY
  619.   local prevX, prevY
  620.   prevX = currPos.x
  621.   prevY = currPos.y
  622.  
  623.   -- Update the current co-ordinates
  624.   if (currOrient == way.FORWARD) then
  625.     newY = currPos.y - 1
  626.     newX = currPos.x
  627.   elseif (currOrient == way.LEFT) then
  628.     newX = currPos.x + 1
  629.     newY = currPos.y
  630.   elseif (currOrient == way.BACK) then
  631.     newY = currPos.y + 1
  632.     newX = currPos.x
  633.   elseif (currOrient == way.RIGHT) then
  634.     newX = currPos.x - 1
  635.     newY = currPos.y
  636.   else
  637.     writeMessage ("Invalid currOrient in turtleBack function", messageLevel.ERROR)
  638.   end
  639.  
  640.   -- First try to move back using the standard function
  641.   currPos.x = newX
  642.   currPos.y = newY
  643.   local returnVal = turtle.back()
  644.  
  645.   if (returnVal == false) then
  646.     -- Didn't move. Reset the co-ordinates to the previous value
  647.     currPos.x = prevX
  648.     currPos.y = prevY
  649.  
  650.     turtle.turnRight()
  651.     turtle.turnRight()
  652.  
  653.     -- Try to move by using the forward function (note, the orientation will be set as
  654.     -- the same way as this function started because if the function stops, that is the
  655.     -- way that we want to consider the turtle to be pointing)
  656.     returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.compare, turtle.suck, maximumGravelStackSupported, newX, newY, currPos.z)
  657.  
  658.     if not doNotTurnBack then
  659.       turtle.turnRight()
  660.       turtle.turnRight()
  661.     end
  662.   end
  663.    
  664.   return returnVal
  665. end
  666.  
  667.  
  668. --===========================================================
  669. -- Move turtle on needed position
  670. -- Simple move by x, then y, then z
  671. --===========================================================
  672. function turtleGoTo(x,y,z)
  673.   if not x then x=currPos.x end
  674.   if not y then y=currPos.y end
  675.   if not z then z=currPos.z end
  676.  
  677.   local targetVec = vector.new(x,y,z) - currPos
  678.  
  679.  
  680.   -- X
  681.   if (targetVec.x<0 and currOrient==way.RIGHT)   or
  682.      (targetVec.x>0 and currOrient==way.LEFT)    then
  683.      while currPos.x ~= x do
  684.        turtleBack(true)
  685.      end
  686.   end
  687.  
  688.   while (x<currPos.x) do
  689.     turtleSetOrientation(way.LEFT)
  690.     turtleForward()
  691.   end
  692.   while (x>currPos.x) do
  693.     turtleSetOrientation(way.RIGHT)
  694.     turtleForward()
  695.   end
  696.  
  697.  
  698.   -- Y
  699.   if(targetVec.y<0 and currOrient==way.FORWARD) or
  700.     (targetVec.y>0 and currOrient==way.BACK)    then
  701.      while currPos.y ~= y do
  702.        turtleBack(true)
  703.      end
  704.   end
  705.  
  706.   while (y<currPos.y) do
  707.     turtleSetOrientation(way.BACK)
  708.     turtleForward()
  709.   end
  710.   while (y>currPos.y) do
  711.     turtleSetOrientation(way.FORWARD)
  712.     turtleForward()
  713.   end
  714.  
  715.  
  716.   -- Z
  717.   while (z<currPos.z) do
  718.     turtleDown()
  719.   end
  720.   while (z>currPos.z) do
  721.     turtleUp()
  722.   end
  723. end
  724.  
  725. --===========================================================
  726. -- Move turtle on needed point
  727. --===========================================================
  728. function turtleGoToP(point)
  729.   turtleGoTo(point.x, point.y, point.z)
  730. end
  731.  
  732. --===========================================================
  733. -- Just leave numbers in pattern, if in blacklist is 0
  734. --===========================================================
  735. function selectPatternByBlacklist(pattern, blacklist)
  736.   local resultPattern = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
  737.   for i=1, 16 do
  738.       if(blacklist[i] == 0) then resultPattern[i] = pattern[i] end
  739.   end
  740.   return resultPattern
  741. end
  742.  
  743. --===========================================================
  744. -- Searching if wee have needed item in inventory
  745. --===========================================================
  746. function findInSlotsArrayByPattern(arr, n, blacklist)
  747.   blacklist = blacklist or {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
  748.  
  749.   -- Set indexes to 0 if blacklist here is 1
  750.   local filteredArr = selectPatternByBlacklist(arr, blacklist)
  751.  
  752.   for i=1, 16 do
  753.     if(filteredArr[i] == n) and (turtle.getItemCount(i) > 0) then
  754.       return i
  755.     end
  756.   end
  757.   return 0
  758. end
  759.  
  760.  
  761. -- ********************************************************************************** --
  762. -- **                                                                              ** --
  763. -- **                                                                              ** --
  764. -- **                                                                              ** --
  765. -- **                                                                              ** --
  766. -- **                                                                              ** --
  767. -- **                                PROGRAMS                                      ** --
  768. -- **                                                                              ** --
  769. -- **                                                                              ** --
  770. -- **                                                                              ** --
  771. -- **                                                                              ** --
  772. -- **                                                                              ** --
  773. -- ********************************************************************************** --
  774.  
  775.  
  776. -- ********************************************************************************** --
  777. -- Go to the storage and suck needed blocks. Storage must be defined
  778. -- ********************************************************************************** --
  779. function reloadForFilling(slotsPattern, blacklistPattern)
  780.  
  781.   local reloadedPattern = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
  782.  
  783.   -- Default blacklist. No thrash to drop
  784.   if(blacklistPattern==nil) then blacklistPattern = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} end
  785.  
  786.   -- First, unload blacklisted slotls
  787.   -- This is blocks that we dont using for building
  788.   for i=1, 16 do
  789.     if( blacklistPattern[i] > 0) then
  790.       turtleGoTo(0,0,0)
  791.       turtleSetOrientation(way.LEFT)
  792.      
  793.       turtle.select(i)
  794.       turtle.drop()
  795.     end
  796.   end
  797.  
  798.   -- Then move to storages and take blocks
  799.   for i=1, 16 do
  800.     local itemSpace = turtle.getItemSpace(i)
  801.     if( itemSpace > 0  and (slotsPattern[i] > 0)) then
  802.       turtleGoTo((slotsPattern[i]-1)*2, 0, 0)
  803.       turtleSetOrientation(way.BACK)
  804.       turtle.select(i)
  805.       if( turtle.suck(itemSpace) ) then
  806.         -- Yes, we sucked something. Lets write it in pattern
  807.         reloadedPattern[i] = 1
  808.       end
  809.     end
  810.   end
  811.  
  812.   return reloadedPattern
  813. end
  814.  
  815. -- ********************************************************************************** --
  816. -- Place item in front of turtle. Check if item already placed.
  817. -- ********************************************************************************** --
  818. function placeBlock(itemSlot, direction)
  819.  
  820.   local detectFnc, compareFnc, placeFnc, attackFnc =
  821.         turtle.detect, turtle.compare, turtle.place,turtle.attack
  822.  
  823.   if( direction == way.UP ) then
  824.     detectFnc, compareFnc, placeFnc, attackFnc =
  825.     turtle.detectUp, turtle.compareUp, turtle.placeUp, turtle.attackUp
  826.   elseif( direction == way.DOWN )then
  827.     detectFnc, compareFnc, placeFnc, attackFnc =
  828.     turtle.detectDown, turtle.compareDown, turtle.placeDown, turtle.attackDown
  829.   end
  830.  
  831.   -- slotsPattern is array of 16 nubbers that represent
  832.   -- what kind of blocks lying in what kind of
  833.   if(itemSlot == nil) then
  834.     selectNonEmptySlot()
  835.   else
  836.     turtle.select(itemSlot)
  837.   end
  838.  
  839.   local placeSucces = false
  840.   local digCount = 0
  841.   local maxDigCount = 20
  842.  
  843.  
  844.   -- Check if there is already item  then try to place
  845.   placeSucces = placeFnc()
  846.  
  847.   if((not placeSucces) and detectFnc()) then
  848.     if(compareFnc()) then
  849.       -- Item that we must set already here
  850.       return true
  851.     else
  852.       -- There is something else. Dig/Attack and place item
  853.       turtleDig(direction)
  854.       digCount = digCount + 1
  855.     end
  856.   end
  857.  
  858.   -- Now try to place item until item will placed
  859.   while ((placeSucces == false) and (digCount < maxDigCount)) do
  860.     if (detectFnc()) then
  861.       if(digCount > 0) then
  862.         sleep(0.1)
  863.       end
  864.       turtleDig(direction)
  865.       digCount = digCount + 1
  866.     else
  867.        -- Am being stopped from moving by a mob, attack it
  868.        attackFnc()
  869.     end
  870.     -- Try the place again
  871.     placeSucces = placeFnc()
  872.   end
  873.  
  874.   return placeSucces
  875. end
  876.  
  877. -- ********************************************************************************** --
  878. -- Select non-empty slot
  879. -- ********************************************************************************** --
  880. function selectNonEmptySlot()
  881.   for i=1, 16 do
  882.     if( turtle.getItemCount(i) > 0) then
  883.       turtle.select(i)
  884.       return true
  885.     end
  886.   end
  887.   return false
  888. end
  889.  
  890. -- ********************************************************************************** --
  891. -- Get slot pattern.
  892. -- Returning array(16) that represent indexes in slots
  893. -- ********************************************************************************** --
  894. function getSlotsPattern()
  895.   local ptattern = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} -- Standart pattern. All slots empty
  896.   local lastUnemptySlot = 0
  897.   local lastEnum = 1
  898.  
  899.   for i=1, 16 do
  900.     turtle.select(i)
  901.     if( turtle.getItemCount(i) > 0) then
  902.       if (lastUnemptySlot == 0) then
  903.         lastUnemptySlot = i
  904.       elseif (i>1) and (turtle.compareTo(lastUnemptySlot) == false) then
  905.         lastEnum = lastEnum + 1
  906.         lastUnemptySlot = i
  907.       end
  908.      
  909.       ptattern[i] = lastEnum
  910.     end
  911.   end
  912.   return ptattern
  913. end
  914.  
  915.  
  916. -- ********************************************************************************** --
  917. -- Fill territory by blocks pattern
  918. --
  919. -- ********************************************************************************** --
  920. function fill(sizeX, sizeY, sizeZ, patternId, pos, isGoBackAfterFill, fillFlags)
  921.  
  922.   -- ==============================
  923.   -- Variables
  924.   -- ==============================
  925.   if not pos then pos = vector.new() end -- Default position: zero
  926.  
  927.   if not patternId then patternId = 'plain' end -- Default pattern index - plain fill
  928.   if not isGoBackAfterFill then isGoBackAfterFill = true end -- Default returning - yes, go back
  929.  
  930.   -- Pattern sizes per axis
  931.   local ptSzX = #fillPattern[patternId][1][1]
  932.   local ptSzY = #fillPattern[patternId][1]
  933.   local ptSzZ = #fillPattern[patternId]
  934.  
  935.   -- There we will storage what slots was deplited, out of building blocks
  936.   -- 0: slot in use, have blocks.
  937.   -- 1: slot deplited, haven't blocks or have thrash
  938.   local blacklistPattern = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
  939.  
  940.   local totalVolume = sizeX*sizeY*sizeZ -- Total volume of blocks
  941.   local vol = {{{}}} -- 3d array of whole volume filling territory
  942.  
  943.  
  944.   -- Statistics
  945.   local totalBlocksToPlace    = 0  -- Total count of blocks that must be placed
  946.   local totalBlocksCountArray = {} -- Blocks count by indexes
  947.   local totalFuelNeeded       = 0
  948.  
  949.  
  950.   -- ==============================
  951.   -- Preparing
  952.   -- At first, we must make a large
  953.   -- array of all blocks in volume
  954.   -- ==============================
  955.   for O=0, totalVolume-1 do
  956.     local u, v, w
  957.     u = math.floor(O/(sizeX*sizeY)) -- z
  958.     v = math.floor(O/sizeX) % sizeY -- y
  959.     w = math.floor(O%sizeX)         -- x
  960.    
  961.  
  962.     -- Pattern picker must think we are on this 'imagined' or 'fabled' positions
  963.     local fabled_u, fabled_v, fabled_w = u,v,w
  964.     if(fillFlags['mirror -1'] or fillFlags['mirror -1z']) then
  965.       fabled_u = u + math.floor( (u+ptSzZ-1) / (ptSzZ*2-1) )
  966.     end
  967.     if(fillFlags['mirror -1'] or fillFlags['mirror -1y']) then
  968.       fabled_v = v + math.floor( (v+ptSzY-1) / (ptSzY*2-1) )
  969.     end
  970.     if(fillFlags['mirror -1'] or fillFlags['mirror -1x']) then
  971.       fabled_w = w + math.floor( (w+ptSzX-1) / (ptSzX*2-1) )
  972.     end
  973.  
  974.     -- Compute pattern array indexes. Place on pattern that we want to take
  975.     local ptX, ptY, ptZ = fabled_w%ptSzX, fabled_v%ptSzY, fabled_u%ptSzZ
  976.    
  977.     -- Flag "mirror" must mirrored all coordinates on even step
  978.     if(fillFlags['mirror'] or fillFlags['mirror -1'] or fillFlags['mirror -1x'] or
  979.        fillFlags['mirror -1y'] or fillFlags['mirror -1z']) then
  980.       if (math.floor(fabled_w/ptSzX) % 2) == 1 then ptX = ptSzX-ptX-1 end
  981.       if (math.floor(fabled_v/ptSzY) % 2) == 1 then ptY = ptSzY-ptY-1 end
  982.       if (math.floor(fabled_u/ptSzZ) % 2) == 1 then ptZ = ptSzZ-ptZ-1 end
  983.     end
  984.  
  985.  
  986.     -- Get block index from pattern, demands on position of turtle
  987.     local blockIndex = tonumber(getChar(fillPattern[patternId][ptZ+1][ptY+1], ptX+1))
  988.    
  989.     -- When we use 'sides' or 'corners' flags, we avoid all blocks inside volume
  990.     if fillFlags['sides'] or fillFlags['corners'] then
  991.       if(u>0 and u<sizeZ-1) and (v>0 and v<sizeY-1) and (w>0 and w<sizeX-1) then
  992.         blockIndex = 0
  993.       end
  994.     end
  995.    
  996.     -- If only 'sides' flag enabled, clear all corners
  997.     if fillFlags['sides'] and not fillFlags['corners'] then
  998.       if not(((u>0 and u<sizeZ-1) and (v>0 and v<sizeY-1)) or
  999.              ((u>0 and u<sizeZ-1) and (w>0 and w<sizeX-1)) or
  1000.              ((w>0 and w<sizeX-1) and (v>0 and v<sizeY-1))) then
  1001.         blockIndex = 0
  1002.       end
  1003.     end
  1004.    
  1005.     -- If only 'corners', clear all sides
  1006.     if fillFlags['corners'] and not fillFlags['sides'] then
  1007.       if not(((u==0 or u==sizeZ-1) and (v==0 or v==sizeY-1)) or
  1008.              ((u==0 or u==sizeZ-1) and (w==0 or w==sizeX-1)) or
  1009.              ((w==0 or w==sizeX-1) and (v==0 or v==sizeY-1))) then
  1010.         blockIndex = 0
  1011.       end
  1012.     end
  1013.     if fillFlags['tunnel'] and (w==0 or w==sizeX-1) and (u>0 and u<sizeZ-1) and (v>0 and v<sizeY-1) then
  1014.       blockIndex = 0
  1015.     end
  1016.     if fillFlags['tube'] and (u==0 or u==sizeZ-1) and (w>0 and w<sizeX-1) and (v>0 and v<sizeY-1) then
  1017.       blockIndex = 0
  1018.     end
  1019.     if fillFlags['clearAllSkipped'] then if blockIndex== nil then blockIndex = 0 end end
  1020.     if fillFlags['skipClearing']    then if blockIndex==   0 then blockIndex = nil end end
  1021.    
  1022.     -- Clear all blocks, ignoring any pattern
  1023.     if fillFlags['clear'] then blockIndex = 0 end
  1024.  
  1025.  
  1026.     -- Add tables if they are not defined
  1027.     if not vol[u]       then vol[u]       = {} end
  1028.     if not vol[u][v]    then vol[u][v]    = {} end
  1029.     if not vol[u][v][w] then vol[u][v][w] = {} end
  1030.    
  1031.     -- Put block index in volume array
  1032.     vol[u][v][w] = blockIndex
  1033.    
  1034.     -- Statistics
  1035.     if blockIndex ~= nil and blockIndex ~= 0 then
  1036.    
  1037.       -- Create key for new type
  1038.       if not totalBlocksCountArray[blockIndex] then totalBlocksCountArray[blockIndex] = 0 end
  1039.    
  1040.       -- Increment counters
  1041.       if(blockIndex>0)then
  1042.         totalBlocksToPlace = totalBlocksToPlace + 1
  1043.         totalBlocksCountArray[blockIndex] = totalBlocksCountArray[blockIndex] + 1
  1044.       end
  1045.     end
  1046.   end
  1047.  
  1048.   -- More statistics
  1049.   totalFuelNeeded = sizeX*sizeY*(2 + math.floor(sizeZ/3))
  1050.  
  1051.  
  1052.  
  1053.   -- ==============================
  1054.   -- Info screen
  1055.   -- ==============================
  1056.  
  1057.   clear()
  1058.   print('---------INFO---------:\n'..
  1059.   'Minimum fuel needed:   '..totalFuelNeeded)
  1060.  
  1061.   -- Print how much we need of blocks by each type
  1062.   for k,v in pairs(totalBlocksCountArray) do
  1063.     local stacks   = math.floor(v/64)
  1064.     local modStacks= v%64
  1065.     print(' #'..k..': '..((stacks>0) and stacks..'x64' or '')..
  1066.       ((stacks>0 and modStacks>0) and ' + ' or '')..
  1067.       ((modStacks>0) and modStacks or '') )
  1068.   end
  1069.   print('Press ENTER')
  1070.  
  1071.   -- Wait while user press key
  1072.   read()
  1073.  
  1074.  
  1075.  
  1076.   -- ==============================
  1077.   -- Functions
  1078.   -- ==============================
  1079.  
  1080.   -- Compute slots pattern. Pattern shows what block index in whitch slot
  1081.   local slotsPattern = getSlotsPattern()
  1082.   local startPos = vector.new(currPos.x, currPos.y, currPos.z)
  1083.  
  1084.  
  1085.   -- Function same as GoTo, but consider position of building and incremental shifting
  1086.   local fillGoToFnc = function(x,y,z)
  1087.     -- Shift next coord with flags
  1088.     -- Userful for stairs and diagonals
  1089.     local shift = vector.new()
  1090.     if y then shift.x = y*(fillFlags['x++'] and 1 or (fillFlags['x--'] and -1 or 0)) end
  1091.     if x then shift.y = x*(fillFlags['y++'] and 1 or (fillFlags['y--'] and -1 or 0)) end
  1092.     if y then shift.z = y*(fillFlags['z++'] and 1 or (fillFlags['z--'] and -1 or 0)) end
  1093.    
  1094.     local changeVec = pos + shift    
  1095.    
  1096.     -- nil means we dont need change current position
  1097.     if not x then x = currPos.x-changeVec.x end
  1098.     if not y then y = currPos.y-changeVec.y end
  1099.     if not z then z = currPos.z-changeVec.z end
  1100.  
  1101.     local targetPos = vector.new(x,y,z) + changeVec
  1102.     turtleGoToP(targetPos)
  1103.   end
  1104.  
  1105.  
  1106.   -- If we handle some unsolutionabled error, we can hope only on user.
  1107.   -- Going to start and waiting until he fix all
  1108.   local backToStartFnc = function(msg)
  1109.     writeMessage(msg, messageLevel.ERROR)
  1110.    
  1111.     turtleGoTo(0,0,0)
  1112.     turtleSetOrientation(way.FORWARD)
  1113.    
  1114.     pressAnyKey()
  1115.   end
  1116.  
  1117.   -- Go to start and try reload while accomplished
  1118.   local reloadFnc = function(blockIndex)
  1119.  
  1120.     -- Up over structure if volume
  1121.     if(currPos.y ~= 0) then
  1122.       turtleGoTo(currPos.x, currPos.y, sizeZ+1)
  1123.     end
  1124.  
  1125.     local isReloaded = false
  1126.    
  1127.     while isReloaded==false do
  1128.       turtleGoTo(0, 0, 0)
  1129.       local reloadedPattern = reloadForFilling(slotsPattern, blacklistPattern)
  1130.      
  1131.       -- If some slots was not reloaded, leave them in blacklist
  1132.       for i=1, 16 do
  1133.         if(reloadedPattern[i] > 0) then
  1134.           blacklistPattern[i] = 0
  1135.         end
  1136.       end
  1137.      
  1138.       -- Check if we reloaded needed blockIndex
  1139.       if findInSlotsArrayByPattern(slotsPattern, blockIndex, blacklistPattern) == 0 then
  1140.         backToStartFnc('Error: Reloading failed. Please make storage and press any key')
  1141.       else
  1142.         isReloaded = true
  1143.       end
  1144.     end
  1145.   end
  1146.  
  1147.  
  1148.   -- The main function of placing blocks with parameters
  1149.   local fillFnc = function(x,y,z,direct,orient, blockIndex)
  1150.  
  1151.     -- Error text only for fatals, where program cant do nothing
  1152.     local fillError
  1153.    
  1154.     repeat -- Repeat until no fillErrors
  1155.       fillError = nil
  1156.      
  1157.       if( blockIndex ~= nil) then  
  1158.         if blockIndex > 0 then
  1159.           local slotWithNeededItem = findInSlotsArrayByPattern(slotsPattern, blockIndex, blacklistPattern)
  1160.           if(slotWithNeededItem ~= 0) then
  1161.             fillGoToFnc(x,y,z)
  1162.             if(orient)then turtleSetOrientation(orient) end -- Can be nil - orientation don't matter
  1163.            
  1164.             -- We have block and can put it on place
  1165.             placeBlock(slotWithNeededItem, direct)
  1166.            
  1167.             -- If slot was emptyed, we must note, that now there will be thrash
  1168.             -- Each next time when turtle dig, empty slot will filling
  1169.             if(turtle.getItemCount(slotWithNeededItem) == 0) then
  1170.               blacklistPattern[slotWithNeededItem] = 1
  1171.              
  1172.               -- Check again if we have another slot with item
  1173.               if( findInSlotsArrayByPattern(slotsPattern, blockIndex, blacklistPattern) == 0)then
  1174.                 -- No avaliable blocks to build!
  1175.                 -- Save coords, reload and return
  1176.                 local buildProgressStopPos = vector.new(currPos.x, currPos.y, currPos.z)
  1177.                 local stopOrient = currOrient
  1178.                
  1179.                 reloadFnc(blockIndex)
  1180.                
  1181.                 -- Go back to work
  1182.                 turtleGoTo(0, 0, 0)
  1183.                 turtleGoTo(0, 0, sizeZ+1)
  1184.                 turtleGoToP(buildProgressStopPos)
  1185.               end
  1186.             end
  1187.           else
  1188.             -- Fatal fillError. We are probably reloaded, but still havent blocks to place
  1189.             -- This can happend only with bug in code
  1190.             fillError = 'Fatal fillError: No blocks to place on {'..x..','..y..','..z..'}\nI dont know what went wrong.'
  1191.             backToStartFnc(fillError)
  1192.           end
  1193.         else -- blockIndexToPlace == 0
  1194.           fillGoToFnc(x,y,z)
  1195.           if(orient)then turtleSetOrientation(orient) end -- Can be nil - orientation don't matter
  1196.          
  1197.           -- Remove block here and do nothing
  1198.           turtleDig(direct)
  1199.         end
  1200.       else -- blockIndexToPlace == nil
  1201.        
  1202.       end
  1203.     until not fillError
  1204.    
  1205.     return nil
  1206.   end -- fillFnc()
  1207.  
  1208.  
  1209.   -- ==============================
  1210.   -- Iterators
  1211.   -- ==============================
  1212.  
  1213.  
  1214.   -- move to start position
  1215.   fillGoToFnc(0, 0, ((sizeZ>1) and 1 or 0))
  1216.  
  1217.   -- y-> is printing method, when we fill from us to forward
  1218.   if     fillFlags['y->'] then
  1219.     for _y=0, sizeY-1 do
  1220.       for _z=0, sizeZ-1 do
  1221.         for _x=0, sizeX-1 do
  1222.           local x,y,z = _x,_y,_z
  1223.           if(z%2==1) then x = sizeX-x-1 end -- Ping-pong
  1224.          
  1225.           fillFnc(x,y,z+1, way.DOWN, nil, vol[z][y][x])
  1226.         end
  1227.       end
  1228.     end
  1229.    
  1230.   -- Printer working as usual building programs
  1231.   elseif fillFlags['printer'] then
  1232.     for _z=0, sizeZ-1 do
  1233.       for _y=0, sizeY-1 do
  1234.         for _x=0, sizeX-1 do
  1235.           local x,y,z = _x,_y,_z
  1236.           if(z%2==1) then y = sizeY-y-1; x = sizeX-x-1 end -- Ping-pong
  1237.           if(y%2==1) then x = sizeX-x-1 end                -- Ping-pong
  1238.          
  1239.           fillFnc(x,y,z+1, way.DOWN, nil, vol[z][y][x])
  1240.         end
  1241.       end
  1242.     end
  1243.    
  1244.   -- And most awesome and fast filling method
  1245.   -- It filling 3 blocks per move
  1246.   else
  1247.     local zStepsCount    = math.ceil(sizeZ/3)-1 -- Count of levels, where robot moves horisontally
  1248.     local lastZStepIsCap = (sizeZ%3 == 1) -- The top level of volume is last level where turtle moves hor-ly
  1249.     local zLastStepLevel = zStepsCount*3+(lastZStepIsCap and 0 or 1) -- Z level where turtle will move last
  1250.    
  1251.     for _z=0, zStepsCount do
  1252.       for _y=0, sizeY-1 do
  1253.         for _x=0, sizeX-1 do
  1254.           local x,y = _x,_y
  1255.           x = sizeX - x - 1 -- Revert X coordinates. Filling will be from right to left
  1256.          
  1257.           local z = _z*3+1
  1258.           local currZStepIsLast = (_z==zStepsCount)
  1259.           if currZStepIsLast then z = zLastStepLevel end -- Cap of volume
  1260.          
  1261.           -- Ping-pong
  1262.           local currZIsEven = (_z%2==0)
  1263.           local horisontDirect = way.BACK -- Specific orientation, when we move to next Y pos
  1264.           local horisontShift  = -1       -- Y direction, when we move to next Y pos
  1265.           if not currZIsEven then
  1266.             y = sizeY - y - 1
  1267.             horisontDirect = way.FORWARD
  1268.             horisontShift = 1
  1269.           end          
  1270.          
  1271.           local escapeShaftHere = (x==0 and y==0)
  1272.           local hereWeWillGoUp = ((x==0 and ((_z%2==0 and y==sizeY-1) or (_z%2==1 and y==0))) and _z < zStepsCount)
  1273.          
  1274.  
  1275.           -- Fill down
  1276.           if z>0 and not (lastZStepIsCap and currZStepIsLast) and not escapeShaftHere then
  1277.             fillFnc(x,y,z, way.DOWN, nil, vol[z-1][y][x])
  1278.           end
  1279.          
  1280.           -- Fill forward
  1281.           if x < sizeX-1 then
  1282.             fillFnc(x,y,z, way.FORWARD, way.RIGHT, vol[z][y][x+1])
  1283.           end
  1284.          
  1285.           -- Fill back previous line when we starting new x line
  1286.           if not currZStepIsLast or (not currZIsEven and currZStepIsLast) then
  1287.             if x==0 and ((currZIsEven and y>0) or ((not currZIsEven) and y<sizeY-1)) and
  1288.              not (x==0 and y==1 and currZIsEven) then
  1289.               fillFnc(x,y,z, way.FORWARD, horisontDirect, vol[z][y+horisontShift][x])
  1290.             end
  1291.           end
  1292.          
  1293.           -- Fill UP
  1294.           if z<sizeZ-1 and not hereWeWillGoUp and (not escapeShaftHere or currZStepIsLast) then
  1295.             fillFnc(x,y,z, way.UP, nil, vol[z+1][y][x])
  1296.           end
  1297.          
  1298.           -- Go forward if we finished the line
  1299.           if x==0 and ((_z%2==0 and y<sizeY-1) or (_z%2==1 and y>0)) then
  1300.             turtleGoTo(currPos.x, currPos.y-horisontShift, currPos.z)
  1301.           end
  1302.          
  1303.           -- Move up and fill bocks down, if we advance to next Z level
  1304.           if hereWeWillGoUp then
  1305.             local nextZLevel = (_z+1)*3 + 1
  1306.             if lastZStepIsCap and (_z+1==zStepsCount) then nextZLevel = nextZLevel-1 end -- Cap of volume
  1307.             if(escapeShaftHere)then
  1308.               fillGoToFnc(nil, nil, nextZLevel)
  1309.             else
  1310.               for zAdvance=z+1, nextZLevel do
  1311.                 fillGoToFnc(x,y,zAdvance)
  1312.                 fillFnc(x,y,zAdvance, way.DOWN, nil, vol[zAdvance-1][y][x])
  1313.               end
  1314.             end
  1315.           end
  1316.          
  1317.         end
  1318.       end
  1319.     end
  1320.    
  1321.     -- We use our shaft to go back to x=0, y=0
  1322.     if not (zStepsCount%2==1) then
  1323.       for y=sizeY-2, 0, -1 do
  1324.         fillFnc(0, y, zLastStepLevel, way.FORWARD, way.FORWARD, vol[zLastStepLevel][y+1][0])
  1325.       end
  1326.     end
  1327.    
  1328.     -- And then go down to z 0
  1329.     for z=zLastStepLevel-1, 0, -1 do
  1330.       fillFnc(0, 0, z, way.UP, nil, vol[z+1][0][0])
  1331.     end
  1332.     fillGoToFnc(0,0,0)
  1333.    
  1334.     -- And last block
  1335.     fillFnc(0, -1, 0, way.FORWARD, way.FORWARD, vol[0][0][0])
  1336.   end
  1337.  
  1338.  
  1339.   -- ==============================
  1340.   -- Finishing
  1341.   -- ==============================
  1342.  
  1343.   -- Now we finished filling territory. Just go home
  1344.   if isGoBackAfterFill == true then
  1345.     turtleGoTo(startPos.x, startPos.y, startPos.z)
  1346.     turtleSetOrientation(way.FORWARD)
  1347.   end
  1348.  
  1349.   return true
  1350. end
  1351.  
  1352. -- ********************************************************************************** --
  1353. -- **                                                                              ** --
  1354. -- **                                                                              ** --
  1355. -- **                                                                              ** --
  1356. -- **                                                                              ** --
  1357. -- **                                                                              ** --
  1358. -- **                            Startup functions                                 ** --
  1359. -- **                                                                              ** --
  1360. -- **                                                                              ** --
  1361. -- **                                                                              ** --
  1362. -- **                                                                              ** --
  1363. -- **                                                                              ** --
  1364. -- ********************************************************************************** --
  1365. local args = { ... }
  1366.  
  1367. startupMode = {
  1368.   'Fill', 'Lake drying'
  1369. }
  1370.  
  1371.  
  1372. function init()
  1373.  
  1374.   -- add to patterns all .nfa files
  1375.   local allFiles = fs.list('')
  1376.   local only_nfa = {}
  1377.   for k,v in pairs(allFiles) do
  1378.     if(string.sub(v,#v-3,#v) == '.nfa')then
  1379.       fillPattern[v] = loadNFA(v)
  1380.     end
  1381.   end
  1382.  
  1383.  
  1384.   -- Detect whether this is a wireless turtle, and if so, open the modem
  1385.   local peripheralConnected = peripheral.getType("right")
  1386.   if (peripheralConnected == "modem") then
  1387.     isWirelessTurtle = true
  1388.   end
  1389.    
  1390.   -- If a wireless turtle, open the modem
  1391.   if (isWirelessTurtle == true) then
  1392.     turtleId = os.getComputerLabel()
  1393.     rednet.open("right")
  1394.   end
  1395.  
  1396.   clear()
  1397.  
  1398.   local welcomingText =
  1399. [[=======================================
  1400. == Krutoy Turtle - universal builder ==
  1401. =======================================
  1402. ]]
  1403.   while true do
  1404.     local paramsLine = welcomingText
  1405.     local separator = '----------------------\n'
  1406.     local result = 0
  1407.     local currLine = 'Select mode:\n'
  1408.     local n = 1
  1409.    
  1410.     for k,v in pairs(startupMode) do
  1411.       currLine = currLine..' '..n..' - '..v..'\n'
  1412.       n = n+1
  1413.     end
  1414.     result = readNumberParametr(paramsLine..currLine, 1, #startupMode)
  1415.     local mode = startupMode[result]
  1416.    
  1417.    
  1418.     if(mode == 'Lake drying') then
  1419.       while turtle.getItemCount(1) == 0 do
  1420.           clear()
  1421.           print('Place buket in first slot')
  1422.           sleep(1)
  1423.       end
  1424.      
  1425.       currLine = 'Specify size by x y z (z is deph), separate with spaces, and press ENTER:\n'
  1426.       result = readTableOfNumbers(currLine, false, 3, "%S+")
  1427.       local sizeX,sizeY,sizeZ = result[1],result[2] ,result[3]
  1428.      
  1429.      
  1430.       turtle.select(1)
  1431.       turtle.refuel()
  1432.       local startPos = vector.new(currPos.x,currPos.y,currPos.z)
  1433.       for z=0,sizeZ-1 do
  1434.         for x=0,sizeX-1 do
  1435.           for y=0,sizeY-1 do
  1436.             if(x%2==1) then y = sizeY - y - 1 end -- Ping-pong
  1437.             turtleGoTo(x,y+1,-z)
  1438.             turtle.placeDown()
  1439.             turtle.refuel()
  1440.            
  1441.             clear()
  1442.             print('Fuel level: '..turtle.getFuelLevel())
  1443.           end
  1444.         end
  1445.       end
  1446.       turtleGoTo(nil, nil, startPos.z)
  1447.       turtleGoToP(startPos)
  1448.       turtleSetOrientation(way.FORWARD)
  1449.     end
  1450.    
  1451.      
  1452.    
  1453.     if(mode == 'Fill') then
  1454.       local sizeX,sizeY,sizeZ
  1455.       local pattern = nil
  1456.       local pos = vector.new(0,1,0) -- Trutle build start is block forward of it
  1457.       local fillFlags = {}
  1458.      
  1459.       if not IDE then
  1460.         paramsLine = paramsLine..'MODE:    Fill\n'
  1461.         currLine = 'Select fill pattern:\n'
  1462.         n = 1
  1463.         for k,v in pairs(fillPattern) do
  1464.           currLine = currLine..' '..n..' - '..k..'\n'
  1465.           n = n+1
  1466.         end
  1467.         result = readNumberParametr(paramsLine..separator..currLine, 1, n)
  1468.         n = 1
  1469.         for k,v in pairs(fillPattern) do
  1470.           if(n == result) then
  1471.             pattern = k
  1472.             paramsLine = paramsLine..'PATTERN: '..pattern..'\n'
  1473.             break
  1474.           end
  1475.           n = n+1
  1476.         end
  1477.        
  1478.        
  1479.         currLine = 'Specify size by x y z, separate with spaces, and press ENTER:\n'
  1480.         result = readTableOfNumbers(paramsLine..separator..currLine, false, 3, "%S+")
  1481.         sizeX,sizeY,sizeZ = result[1],result[2],result[3]
  1482.         paramsLine = paramsLine..'SIZE:    {'..sizeX..', '..sizeY..', '..sizeZ..'}\n'
  1483.        
  1484.        
  1485.         currLine = 'Add flags if need, separate with commas, and press ENTER\n'
  1486.         result = readTable(paramsLine..separator..currLine, true, "%s*([^,]+)")
  1487.         if(result) then fillFlags = makeSet(result) end
  1488.       else
  1489.         sizeX,sizeY,sizeZ, pattern, pos, fillFlags =
  1490.             5, 5, 9,'BoxGrid', vector.new(), {}
  1491.       end
  1492.      
  1493.      
  1494.       ---------------------------------------
  1495.       fill(sizeX,sizeY,sizeZ, pattern, pos, true, fillFlags)
  1496.     end
  1497.   end
  1498. end
  1499.  
  1500.  
  1501. init()
RAW Paste Data