-- resumable signed-volume miner with start offset, slow start, return+dual-dump (fixed nil compares) local ST="mine_state.txt" local t=turtle -- read number or "quit"/"resume" local function rd(p) io.write(p..": ") local s=read() or "" s=s:lower() if s=="quit" then error() end if s=="resume" then return "resume" end local n=tonumber(s) if not n then return rd(p) end return n end local function save(S) local h=fs.open(ST,"w"); h.write(textutils.serialize(S)); h.close() end local function load() if not fs.exists(ST) then return nil end local h=fs.open(ST,"r"); local s=h.readAll(); h.close() return textutils.unserialize(s) end -- dig helpers local function digf() while t.detect() do t.dig() end end local function dgu() while t.detectUp() do t.digUp() end end local function dgd() while t.detectDown() do t.digDown() end end -- state local S=load() -- start or resume safely if not S then local X=rd("X (signed fwd/back)") if X=="resume" then S=load() if not S then print("no saved state"); return end end if not S then local Y=rd("Y (signed up/down)") local Z=rd("Z (signed right/left)") local OX=rd("OffX (signed fwd/back; stand beside first mined)") local OY=rd("OffY (signed up/down)") local OZ=rd("OffZ (signed right/left)") S={ xlen=math.abs(X), ylen=math.abs(Y), zlen=math.abs(Z), xneg=X<0, yneg=Y<0, zneg=Z<0, x=1, y=1, z=1, dir=0, ox=OX or 0, oy=OY or 0, oz=OZ or 0, at_off=false, slow=10, px=0, py=0, pz=0, h=0, sh=0 } S.sh=S.h -- capture initial heading save(S) end else -- ensure required keys exist on old saves S.ox=S.ox or 0; S.oy=S.oy or 0; S.oz=S.oz or 0 S.px=S.px or 0; S.py=S.py or 0; S.pz=S.pz or 0 S.h=S.h or 0; S.sh=S.sh or 0 S.slow=S.slow or 0 S.at_off = S.at_off or false end -- turns and facing local function TL() t.turnLeft(); S.h=(S.h+3)%4 end local function TR() t.turnRight(); S.h=(S.h+1)%4 end local function T2() TL(); TL() end local function face(d) while S.h~=d do if (d-S.h)%4==1 then TR() else TL() end end end -- slow-start pause on first 10 moves local function tick() if S.slow>0 then sleep(5); S.slow=S.slow-1; save(S) end end -- moves track pos local function F() local n=0 while not t.forward() do t.attack(); digf(); n=n+1; if n>50 then return end end if S.h==0 then S.px=S.px+1 elseif S.h==1 then S.pz=S.pz+1 elseif S.h==2 then S.px=S.px-1 else S.pz=S.pz-1 end tick(); save(S) end local function U() local n=0 while not t.up() do t.attackUp(); dgu(); n=n+1; if n>50 then return end end S.py=S.py+1; tick(); save(S) end local function D() local n=0 while not t.down() do t.attackDown(); dgd(); n=n+1; if n>50 then return end end S.py=S.py-1; tick(); save(S) end -- go to start offset once (adjacent space) local function go_off() if S.at_off then return end if S.oy>0 then for i=1,S.oy do dgu(); U() end elseif S.oy<0 then for i=1,-S.oy do dgd(); D() end end if S.oz>0 then TR(); for i=1,S.oz do digf(); F() end; TL() elseif S.oz<0 then TL(); for i=1,-S.oz do digf(); F() end; TR() end if S.ox>0 then for i=1,S.ox do digf(); F() end elseif S.ox<0 then T2(); for i=1,-S.ox do digf(); F() end; T2() end S.at_off=true; save(S) end -- Manhattan goto in carved space local function goto_rel(x,y,z) while S.pyy do dgd(); D() end if S.pxx then face(2); for i=1,S.px-x do digf(); F() end end if S.pzz then face(3); for i=1,S.pz-z do digf(); F() end end end -- dump at home using two chests: y=-1 for cobble/dirt/gravel/sand; y=-2 for everything else local function dump_home() local A={["minecraft:cobblestone"]=1,["minecraft:dirt"]=1,["minecraft:gravel"]=1,["minecraft:sand"]=1} for s=1,16 do local d=t.getItemDetail(s); if d and A[d.name] then t.select(s); t.dropDown() end end face(0); digf(); F() -- (1,0,0) dgd(); D(); dgd(); D() -- (1,-2,0) face(2) -- toward chests for s=1,16 do local d=t.getItemDetail(s); if d and not A[d.name] then t.select(s); t.drop() end end face(0); dgu(); U(); dgu(); U() -- back to y=0 face(2); digf(); F() -- back to (0,0,0) face(0) goto_rel(0,0,0) end -- === run === go_off() if S.xneg then T2() end -- guard missing dims on resume if not (S.xlen and S.ylen and S.zlen) then print("bad state"); return end if not (S.x and S.y and S.z) then S.x=1; S.y=1; S.z=1 end if S.dir==nil then S.dir=0 end while S.y<=S.ylen do if S.dir==1 then T2() end for i=S.x,S.xlen do dgu(); dgd() local last=(i==S.xlen) and (S.z==S.zlen) and (S.y==S.ylen) if not last and i