jille_Jr icon

CC: Tunnel program 2.0

jille_Jr | PRO | 11/15/20 04:52:01 PM UTC (Edited) | 0 ⭐ | 369 👁️ | Never ⏰ | []
Lua |

4.85 KB

|

None

|

0 👍

/

0 👎

local tArgs = {...}
 
local LEFT = 0
local FORWARD = 1
local RIGHT = 2
 
local nCurrentDir = FORWARD
 
local nCurrentX = 0
local nCurrentY = 0
 
--(( Functions ))--
 
local function look(nDir)
  while nDir < nCurrentDir do
    turtle.turnLeft()
    nCurrentDir = nCurrentDir - 1
  end
  while nDir > nCurrentDir do
    turtle.turnRight()
    nCurrentDir = nCurrentDir + 1
  end
end
 
local function _go(move, suffix)
  while not turtle[move]() do
    if not turtle["dig"..suffix]() then
      if turtle["detect"..suffix]() then
        error("Bedrock while trying to move " .. move, 0)
      end
      turtle["attack"..suffix]()
    end
  end
end
 
local function goForward()
  _go("forward", "")
  if nCurrentDir == RIGHT then
    nCurrentX = nCurrentX + 1
  elseif nCurrentDir == LEFT then
    nCurrentX = nCurrentX - 1
  end
end
 
local function goUp()
  _go("up", "Up")
  nCurrentY = nCurrentY + 1
end
 
local function goDown()
  _go("down", "Down")
  nCurrentY = nCurrentY - 1
end
 
local function goToY(y)
  if nCurrentY < y then
    -- +1 because for loops are inclusive
    for _ = nCurrentY + 1, y, 1 do
      goUp()
    end
  else
    -- -1 because for loops are inclusive
    for _ = nCurrentY - 1, y, -1 do
      goDown()
    end
  end
end
 
---If current `Y` position is higher than the given `Y` coordinate
---then move to said `Y` coordinate.
local function goToYIfHigher(y)
  if nCurrentY > y then
    goToY(y)
  end
end
 
---If current `Y` position is lower than the given `Y` coordinate
---then move to said `Y` coordinate.
local function goToYIfLower(y)
  if nCurrentY < y then
    goToY(y)
  end
end
 
local function goToX(x)
  if nCurrentX < x then
    look(RIGHT)
    -- +1 because for loops are inclusive
    for _ = nCurrentX + 1, x do
      goForward()
    end
  elseif nCurrentX > x then
    look(LEFT)
    -- -1 because for loops are inclusive
    for _ = nCurrentX - 1, x, -1 do
      goForward()
    end
  end
end
 
local function _digTilTop(nHeight)
  -- dig til top-1
  while nCurrentY < nHeight - 2 do
    goUp()
  end
  if nCurrentY <= nHeight - 2 then
    repeat until not turtle.digUp()
  end
end
 
local function _digTilBottom()
  -- dig til bottom+1
  while nCurrentY > 1 do
    goDown()
  end
  if nCurrentY >= 1 then
    repeat until not turtle.digDown()
  end
end
 
local function digColumn(nHeight)
  if nCurrentY < nHeight / 2 then
    -- bot to top
    _digTilBottom()
    _digTilTop(nHeight)
  else
    -- top to bot
    _digTilTop(nHeight)
    _digTilBottom()
  end
end
 
local function digFrame(nHeight, nWidth)
  digColumn(nHeight)
 
  if nWidth == 1 or nWidth == -1 then
    return
  end
 
  if nCurrentX > nWidth / 2 then
    look(LEFT)
  else
    look(RIGHT)
  end
 
  for _ = 1, math.abs(nWidth) - 1 do
    goForward()
    digColumn(nHeight)
  end
end
 
local function adjustForYDiff(nHeight, nYDiff)
  if nYDiff == 0 then
    return
  end
 
  if nYDiff > 0 then
    local lowestY = nYDiff
    goToYIfLower(lowestY)
  else
    local highestY = nHeight + nYDiff - 1
    goToYIfHigher(highestY)
  end
 
  nCurrentY = nCurrentY - nYDiff
end
 
local function goHome()
  goToX(0)
  look(FORWARD)
  goToY(0)
end
 
local function tunnel(nLength, nHeight, nWidth, nYDiff)
  for _ = 1, nLength do
    look(FORWARD)
    goForward()
    adjustForYDiff(nHeight, nYDiff)
    digFrame(nHeight, nWidth)
  end
 
  goHome()
end
 
--(( Error checking ))--
 
local nArgLength = tonumber(tArgs[1])
local nArgHeight = tonumber(tArgs[2] or 2)
local nArgWidth = tonumber(tArgs[3] or 1)
local nArgYDiff = tonumber(tArgs[4] or 0)
 
local function usage(sMsg)
  sMsg = sMsg and (sMsg .. "\n") or ""
  error(sMsg .. "Usage: tunnel <length> [height=2] [width=1] [y-diff=0]", 0)
end
 
if #tArgs==0 then usage("Missing length.") end
if not nArgLength then usage("Invalid length, expected number.") end
if not nArgHeight then usage("Invalid height, expected number.") end
if not nArgWidth then usage("Invalid width, expected number.") end
if not nArgYDiff then usage("Invalid y-diff, expected number.") end
 
if nArgLength <= 0 then usage("Invalid length, negative not supported.") end
if nArgHeight <= 0 then usage("Invalid height, negative not supported.") end
if nArgWidth == 0 then usage("Invalid width, zero not supported.") end
if math.abs(nArgYDiff) > nArgHeight - 1 then usage("Invalid y-diff, cannot be longer than height - 1.") end
 
if nArgLength % 1 ~= 0 then usage("Invalid length, fractions not supported.") end
if nArgHeight % 1 ~= 0 then usage("Invalid height, fractions not supported.") end
if nArgWidth % 1 ~= 0 then usage("Invalid width, fractions not supported.") end
if nArgYDiff % 1 ~= 0 then usage("Invalid y-diff, fractions not supported.") end
 
--(( Main program ))--
 
tunnel(nArgLength, nArgHeight, nArgWidth, nArgYDiff)
 
--(( EOF ))---
 

Comments