-- LOAD DEAD RECKONING API
os.loadAPI("apis/reckon")
-- BEGIN SETUP
-- keep journal files here
local j = "dig.journal/"
-- refuel when fuel < 2560
local lowFuel = 2560
-- resume running when fuel > 7680
local runFuel = 7680
-- allow the turtle to burn coal fuel
-- that it mines. false = not allowed,
-- always return for refueling.
local burnCoal = false
---------------------------------------
-- don't change anything below here. --
---------------------------------------
-- maximum radius
-- seriously, don't change it
-- you'll be sorry if you do...
local rLim = 63
local start = os.clock()
local args = {...}
local r = tonumber(args[1]) or rLim
local d = (tonumber(args[2]) or 2) * 3 - 2
-- calculate how many torches we need
-- to cover the requested radius
local tMin = math.floor(r / 6)
tMin = tMin * tMin
if 0 == tMin then tMin = 1 end
-- bootstrap
if
not fs.exists(j) or
not fs.isDir(j)
then fs.makeDir(j) end
-- make sure the radius is sane
if r > rLim then
print("radius reduced to "..rLim..".")
r = rLim
end
-- load saved arguments
if fs.exists(j.."args") then
local fh = fs.open(j.."args", "r")
r = tonumber(fh.readLine())
d = tonumber(fh.readLine())
fh.close()
-- sanity check again
if r > rLim then r = rLim end
else -- or save them if they don't exist
local fh = fs.open(j.."arguments", "w")
fh.writeLine(r)
fh.writeLine(d)
fh.close()
end
local xs, xe, xd = 1, r, 1
local ys, ye, yd = 1, r, 1
if fs.exists(j.."weave") then
local fh = fs.open(j.."weave", "r")
xs = tonumber(fh.readLine())
xe = tonumber(fh.readLine())
xd = tonumber(fh.readLine())
ys = tonumber(fh.readLine())
ye = tonumber(fh.readLine())
yd = tonumber(fh.readLine())
fh.close()
end
-- END SETUP
-- BEGIN AUXILIARY FUNCTIONS
function tryRefuel ()
for i = 16, 1, -1 do
if 0 ~= turtle.getItemCount(i) then
turtle.select(i)
turtle.refuel()
end
end
end
function refuel ()
if turtle.getFuelLevel() < lowFuel then
print("I need fuel.")
repeat
sleep(5)
tryRefuel()
until turtle.getFuelLevel() > runFuel
end
end
function needTorches ()
if
tMin ~= 1 and
1 == turtle.getItemCount(1)
then
reckon.goHome()
print("I need torches.")
end
repeat sleep(5)
until tMin <= turtle.getItemCount(1)
end
-- place a torch when appropriate
function placeTorch ()
local x, y, z = reckon.getX(),
reckon.getY(),
reckon.getZ()
--[[
rotated grid pattern
BROKEN DO NOT USE
more efficient torch placement
if i ever figure it out...
if not turtle.compareDown() and (
4 == x % 7 and (4 == y or ye - 4 == y) or
4 == y % 7 and (4 == x or xe - 4 == x)
) then -- place every seven on edges
turtle.digDown()
turtle.placeDown()
elseif x > 7 and y > 7 then
-- and on a rotated grid inside
local g = ((x - y) / 16 - y) % 16
if 4 == g or 12 == g then
turtle.digDown()
turtle.placeDown()
end
end
]]--
-- FIXME: this code hurts me.
local xl = x <= r / 2 + 1.5 and 4 == x % 7
local xh = x >= r / 2 + 1.5 and 4 == (r - x) % 7
local yl = y <= r / 2 + 1.5 and 4 == y % 7
local yh = y >= r / 2 + 1.5 and 4 == (r - y) % 7
if (
xl and yl or xl and yh or
xh and yl or xh and yh
) and not turtle.compareDown() then
turtle.digDown()
turtle.placeDown()
end
end
-- fancy zig-zagging
function saveWeaveState ()
local fh = fs.open(j.."weave", "w")
fh.writeLine(xs)
fh.writeLine(xe)
fh.writeLine(xd)
fh.writeLine(ys)
fh.writeLine(ye)
fh.writeLine(yd)
fh.close()
end
function diggum ()
turtle.dig()
turtle.suck()
reckon.forward()
turtle.digUp()
turtle.digDown()
turtle.suckDown()
turtle.suckUp()
end
function nextRow()
-- BUG: batched actions
-- which way to turn? mmm mathy.
local axis = reckon.getF() % 2
local d = (axis * yd + (axis - 1) * xd) + 2
-- weave
if 0 == reckon.getF() % 2 then
xs, xe, xd = xe, xs, -xd
else
ys, ye, yd = ye, ys, -yd
end
saveWeaveState()
reckon.turn(d)
diggum()
reckon.turn(d)
end
function nextLevel()
-- BUG: batched actions
-- weave
xs, xe, xd = xe, xs, -xd
ys, ye, yd = ye, ys, -yd
saveWeaveState()
-- which way to turn? mmm mathy.
local axis = reckon.getF() % 2
local d = (1 + axis * yd - (axis - 1) * xd) / 2
reckon.turn(d)
reckon.down(3)
placeTorch()
end
-- check if inventory needs emptying
function inventoryFull ()
for i = 1, 16 do
if turtle.getItemCount(i) == 0 then
return false
end
end
return true
end
-- END AUXILIARY FUNCTIONS
-- BEGIN MAIN PROGRAM
function saveBookmark ()
local fh = fs.open(j.."bookmark", "w")
for c, c in ipairs({
reckon.getX(), reckon.getY(),
reckon.getZ(), reckon.getF()
}) do fh.writeLine(c) end
fh.close()
end
function needSomething ()
if needTorches() or inventoryFull() or not burnCoal then
saveBookmark()
reckon.goHome()
emptyInventory()
end
if turtle.getFuelLevel() < minFuel then tryRefuel() end
end
-- returning to dig site
function restoreBookmark ()
if not fs.exists(j.."bookmark")
then return end
local fh = fs.open(j.."bookmark", "w")
local x, y, z, f =
tonumber(fh.readLine()), tonumber(fh.readLine()),
tonumber(fh.readLine()), tonumber(fh.readLine())
fh.close()
reckon.gotoZYXF(x, y, z, f)
fs.delete(j.."bookmark")
end
-- digging phase
function goDig ()
digging = true
print("it's off to work i go")
turtle.digUp()
if not turtle.compareDown() then turtle.digDown() end
turtle.suckDown()
turtle.suckUp()
-- actually dig
repeat
repeat
while
0 == reckon.getF() % 2 and reckon.getX() ~= xe or
1 == reckon.getF() % 2 and reckon.getY() ~= ye
do
diggum()
if
inventoryFull() or
turtle.getFuelLevel() < lowFuel
then return false end
end
if
reckon.getX() == xe and
reckon.getY() == ye
then
if reckon.getZ() == d
then return true
else nextLevel() end
else nextRow() end
until cows_come_home
until cows_come_home
end
local phase = 1
function savePhase ()
local fh = fs.open(j.."phase", "w")
fh.writeLine(phase)
fh.close()
end
if fs.exists(j.."phase") then
-- interrupted session
-- pick up where we left off
if reckon.hasState() then
reckon.resume()
end
local fh = fs.open(j.."phase", "r")
phase = tonumber(fh.readLine())
fh.close()
else
-- new session
-- make sure we have enough torches
turtle.select(1)
local t = math.floor(r / 7.1)
t = t * t
if 0 == t then t = 1 end
if turtle.getItemCount(1) < t then
print(
"place at least "..t..
" torch(es) in the first slot to begin."
)
repeat sleep(1)
until turtle.getItemCount(1) >= t
end
-- try to refuel before we complain.
if turtle.getFuelLevel() < lowFuel then tryRefuel() end
if turtle.getFuelLevel() < lowFuel then refuel() end
print("hi hoooooooo!!!")
-- move into 1, 1, 1
reckon.down()
reckon.forward()
end
-- main part of the state engine
repeat
savePhase()
print("calling phase "..phase)
if ({
[0] = needSomething,
[1] = restoreBookmark,
[2] = goDig
})[phase]() then break end
phase = (phase + 1) % 3
until cows_come_home
emptyInventory()
shell.run("cleanup")
start = os.clock() - start
print(string.format(
"complete. elapsed time: %02d:%02d:%02d",
math.floor(start / 3600),
math.floor(start / 60) % 60,
start % 60
))
-- END ALL THE THINGS