quarry.lua
856 lines · 30.1 KB
Rectangular Quarry Program 1.2b by Adam Smith "shiphorns" March 7 2013 1.0b - Original public release 1.1b - Fixes bug with turtle using the wrong axis order when trying to return home after hitting and undiggable block. I erroneously had it trying to do moveTo(0,0,0) instead of goHome() which would result in the turtle trying to move in the x-direction first, and possibly getting blocked by bedrock when trying to move home. 1.2b - Fix for turtle getting stuck if turtle simultaneous encounters bedrock in front and above it. --
Copy & run
wget https://perlytiara.github.io/turtles.tips/raw/programs/perlytiara/quarry/quarry.lua
| 1 | --[[ |
| 2 | |
| 3 | Rectangular Quarry Program 1.2b |
| 4 | by Adam Smith "shiphorns" |
| 5 | March 7 2013 |
| 6 | |
| 7 | 1.0b - Original public release |
| 8 | 1.1b - Fixes bug with turtle using the wrong axis order when trying to return home after hitting |
| 9 | and undiggable block. I erroneously had it trying to do moveTo(0,0,0) instead of goHome() |
| 10 | which would result in the turtle trying to move in the x-direction first, and possibly |
| 11 | getting blocked by bedrock when trying to move home. |
| 12 | 1.2b - Fix for turtle getting stuck if turtle simultaneous encounters bedrock in front and above it. |
| 13 | |
| 14 | --]] |
| 15 | local tArgs = { ... } |
| 16 | local sizeZ -- Quarry is this long in direction turtle is initially facing, including block turtle is on |
| 17 | local sizeX -- Quarry is this wide to the right of where turtle is facing, including block turtle is on |
| 18 | local sizeY -- Quarry removes this many layers of blocks including layer where turtle starts |
| 19 | local bDebug= false |
| 20 | |
| 21 | local goUnload -- Forward declaration |
| 22 | |
| 23 | if (#tArgs == 1) then |
| 24 | sizeZ,sizeX,sizeY = tonumber(tArgs[1]),tonumber(tArgs[1]),256 |
| 25 | elseif (#tArgs == 2) then |
| 26 | sizeZ,sizeX,sizeY = tonumber(tArgs[1]),tonumber(tArgs[2]),256 |
| 27 | elseif (#tArgs >= 3) then |
| 28 | sizeZ,sizeX,sizeY = tonumber(tArgs[1]),tonumber(tArgs[2]),tonumber(tArgs[3]) |
| 29 | if (#tArgs > 3) then |
| 30 | bDebug = (tonumber(tArgs[4])==1) |
| 31 | end |
| 32 | if (#tArgs > 4) then |
| 33 | bStartBelow = (tonumber(tArgs[5])==1) |
| 34 | else |
| 35 | bStartBelow = false |
| 36 | end |
| 37 | if (#tArgs > 5) then |
| 38 | bAutoStart = (tonumber(tArgs[6])==1) |
| 39 | else |
| 40 | bAutoStart = false |
| 41 | end |
| 42 | else |
| 43 | print( "Usage: quarry <sq. size> <optional width > <optional fixed depth> <optional 1 for debug mode> <optional 1 for start below> <optional 1 for auto start>" ) |
| 44 | return |
| 45 | end |
| 46 | |
| 47 | local xSign = 1 |
| 48 | local zSign = 1 |
| 49 | if sizeX < 0 then xSign = -1; sizeX = -sizeX end |
| 50 | if sizeZ < 0 then zSign = -1; sizeZ = -sizeZ end |
| 51 | |
| 52 | -- Validate dimensions |
| 53 | if (sizeX<2 or sizeZ<2 or sizeY<1) then |
| 54 | print( "Dimensions given must be at least 2L x 2W x 1D. Efficiency is optimal if fixed depth is a multiple of 3." ) |
| 55 | return |
| 56 | end |
| 57 | |
| 58 | local minFuel = math.ceil((math.ceil(sizeY/3)*(sizeX*sizeY)+(2*sizeY))/1200) |
| 59 | local maxFuel = "TBD" |
| 60 | |
| 61 | if bAutoStart then |
| 62 | print("Auto-starting quarry (fuel should be in slot 1)...") |
| 63 | else |
| 64 | print("Place fuel reserves in slot 1 (upper left) if desired and hit any key to start.") |
| 65 | os.pullEvent("key") |
| 66 | end |
| 67 | |
| 68 | local tX,tZ,tY = 0,0,0 -- Place the turtle starts is considered block 0,0,0 in the turtle's local coordinate system |
| 69 | local xDir,zDir = 0,1 -- Turtle is considered as initially facing positive z direction, regardless of global world facing direction |
| 70 | local refuelSlot = 1 -- Turtle can fuel from any slot, but it will never dump this slot's contents so this is where fuel should be placed |
| 71 | |
| 72 | -- Define turn functions before using them |
| 73 | local function turnLeft() |
| 74 | turtle.turnLeft() |
| 75 | xDir,zDir = -zDir,xDir |
| 76 | return true |
| 77 | end |
| 78 | |
| 79 | local function turnRight() |
| 80 | turtle.turnRight() |
| 81 | xDir,zDir = zDir,-xDir |
| 82 | return true |
| 83 | end |
| 84 | |
| 85 | -- Apply initial facing adjustments |
| 86 | if zSign == -1 then |
| 87 | turnLeft() |
| 88 | turnLeft() |
| 89 | end |
| 90 | |
| 91 | local myTurnLeft = turnLeft |
| 92 | local myTurnRight = turnRight |
| 93 | if xSign == -1 then |
| 94 | myTurnLeft = turnRight |
| 95 | myTurnRight = turnLeft |
| 96 | end |
| 97 | |
| 98 | -- Debug function assignments |
| 99 | if bDebug then |
| 100 | print("Function assignments complete. myTurnLeft: " .. tostring(myTurnLeft) .. ", myTurnRight: " .. tostring(myTurnRight)) |
| 101 | end |
| 102 | |
| 103 | -- Notice that all coordinates formated as 0,0,0 are in X,Z,Y order, NOT alphabetical X,Y,Z order, where Y is up/down axis |
| 104 | -- Y axis is always the minecraft world Y-axis, but X and Z in this turtle's local coordinate system won't necessarily match his |
| 105 | -- orientation in the global world system (turtle's system is relative to how he is initially facing, +Z is his facing direction) |
| 106 | |
| 107 | local function checkFuel(bMovingAwayFromOrigin) |
| 108 | if bDebug then print("checkFuel()") end |
| 109 | -- This function returns true only if there is enough fuel left to move 1 block in any direction, |
| 110 | -- and still have enough left over for a return trip to 0,0,0 that might be needed for refuel or at |
| 111 | -- the end of the quarrying. This ensures the turtle is never stranded in the quarry. |
| 112 | local fuelLevel = turtle.getFuelLevel() |
| 113 | |
| 114 | if (fuelLevel == "unlimited") then |
| 115 | -- Server has fuel requirement turned off in configs |
| 116 | return true |
| 117 | end |
| 118 | |
| 119 | -- If the turtle is attempting to move away from its starting location, it is going to |
| 120 | -- consume the normal 1 fuel cost to move, but it will also add +1 to the cost of the |
| 121 | -- trip to return home to dump/refuel/finish. If we know the turtle is moving closer to |
| 122 | -- home, there is no extra cost since it is effectively part of the return trip. |
| 123 | local fuelNeeded = math.abs(tX)+math.abs(tY)+math.abs(tZ) |
| 124 | if (bMovingAwayFromOrigin == nil or bMovingAwayFromOrigin == true) then |
| 125 | -- Turtle is moving away from 0,0,0 or direction is unspecified (assume worst case), add 2 fuel |
| 126 | fuelNeeded = fuelNeeded + 2 |
| 127 | end |
| 128 | |
| 129 | if (fuelLevel >= fuelNeeded) then |
| 130 | -- Turtle has enough fuel to do the next 1-block movement, plus enough to |
| 131 | -- return home from there. |
| 132 | return true |
| 133 | end |
| 134 | |
| 135 | -- If we get here, turtle does not have enough fuel for the move plus a return to base |
| 136 | -- First we will try to refuel from anything we find in the turtle's inventory. Failing that |
| 137 | -- We will return to home and prompt the user to add fuel |
| 138 | |
| 139 | local slot = 1 |
| 140 | turtle.select(slot) |
| 141 | |
| 142 | if bDebug then print("Entering while true do in checkFuel") end |
| 143 | while true do |
| 144 | if turtle.refuel(1) then |
| 145 | -- Found fuel in current slot, consume 1, see if it's enough, if not loop again |
| 146 | if (turtle.getFuelLevel()>=fuelNeeded) then |
| 147 | print("Refueled from inventory, resuming quarrying...") |
| 148 | return true |
| 149 | end |
| 150 | else |
| 151 | -- Couldn't refuel from currently-selected slot, try next slot. If there are no more slots, ask for player help. |
| 152 | if (slot < 16) then |
| 153 | slot = slot + 1 |
| 154 | turtle.select(slot) |
| 155 | else |
| 156 | -- There are no more slots to look in, reset selection so that we're ready to loop over all slots again, and so that the |
| 157 | -- player sees slot 1 highlighted (fastest for turtle to find fuel in). Return to 0,0,0 if we can (in case turtle is |
| 158 | -- under lava or otherwise inaccessible), prompt player to add fuel. |
| 159 | |
| 160 | return goUnload(true) |
| 161 | end |
| 162 | end |
| 163 | end |
| 164 | end |
| 165 | |
| 166 | local function goForward(bCheckFuel) |
| 167 | if bDebug then print("goForward()") end |
| 168 | -- Can't move without fuel. checkFuel() will wait on player if necessary. |
| 169 | if (bCheckFuel==true or bCheckFuel==nil) then |
| 170 | checkFuel((xDir>0 and tX>=0) or (xDir<0 and tX<=0) or (zDir>0 and tZ>=0) or (zDir<0 and tZ<=0)) -- Passes boolean true if moving away from 0,0,0 |
| 171 | end |
| 172 | |
| 173 | local tries = 3 |
| 174 | while not turtle.forward() do |
| 175 | if bDebug then print("goForward: while not turtle.forward() do tries="..tries) end |
| 176 | if turtle.detect() then |
| 177 | if bDebug then print("goForward: detect") end |
| 178 | if not turtle.dig() then |
| 179 | print("Undiggable block encountered. Will retry in 5 seconds.") |
| 180 | -- Turtle is blocked. In case this is a temporary glitch, we try 3 times before conceding hard failure |
| 181 | tries = tries - 1 |
| 182 | if (tries <= 0) then |
| 183 | return false |
| 184 | else |
| 185 | if bDebug then print("goForward: sleep(5)") end |
| 186 | sleep(5) -- Wait 5 seconds, hope the problem resolves itself |
| 187 | end |
| 188 | end |
| 189 | elseif turtle.attack() then |
| 190 | if bDebug then print("goForward: attack") end |
| 191 | -- Had to attack player or mob. You can add additional code here such |
| 192 | -- as turtle.suck() if you want to collect killed mob loot. This is a quarry program |
| 193 | -- to collect ores, not rotten flesh and bones, so this block is empty. |
| 194 | else |
| 195 | -- Unknown obstruction, possibly a player in |
| 196 | -- peaceful or creative mode. Try again in 0.5 seconds and hope it's gone. |
| 197 | if bDebug then |
| 198 | print("goForward: sleep(0.5) else block") |
| 199 | print("Turtle fuel="..turtle.getFuelLevel()) |
| 200 | end |
| 201 | sleep(0.5) |
| 202 | end |
| 203 | end |
| 204 | |
| 205 | tX = tX + xDir -- If we're moving in the xDir, this will change tX by + or - 1 |
| 206 | tZ = tZ + zDir -- If we're moving in the zDir, this will change tZ by + or - 1 |
| 207 | |
| 208 | return true -- Turtle moved successfully |
| 209 | end |
| 210 | |
| 211 | local function goDown(bCheckFuel) |
| 212 | if bDebug then print("goDown()") end |
| 213 | -- Can't move without fuel. checkFuel() will wait on player if necessary. |
| 214 | if (bCheckFuel==true or bCheckFuel==nil) then |
| 215 | checkFuel(tY<=0) -- Passes boolean true if moving away from 0,0,0 |
| 216 | end |
| 217 | |
| 218 | local tries = 3 |
| 219 | while not turtle.down() do |
| 220 | if bDebug then print("goDown: while not turtle.down() do tries="..tries) end |
| 221 | if turtle.detectDown() then |
| 222 | if bDebug then print("goDown: detectDown") end |
| 223 | if not turtle.digDown() then |
| 224 | print("Undiggable block encountered. Will retry in 5 seconds") |
| 225 | -- Turtle is blocked. In case this is a temporary glitch, we try 3 times before conceding hard failure |
| 226 | tries = tries - 1 |
| 227 | if (tries <= 0) then |
| 228 | return false |
| 229 | else |
| 230 | if bDebug then print("goDown: sleep(5)") end |
| 231 | sleep(5) -- Wait 5 seconds, hope the problem resolves itself |
| 232 | end |
| 233 | end |
| 234 | elseif turtle.attackDown() then |
| 235 | if bDebug then print("goDown: attack") end |
| 236 | -- Had to attack player or mob. You can add additional code here such |
| 237 | -- as turtle.suck() if you want to collect killed mob loot. This is a quarry program |
| 238 | -- to collect ores, not rotten flesh and bones, so this block is empty. |
| 239 | else |
| 240 | -- Unknown obstruction, possibly a player in |
| 241 | -- peaceful or creative mode. Try again in 0.5 seconds and hope it's gone. |
| 242 | if bDebug then print("goDown: sleep(0.5)") end |
| 243 | sleep(0.5) |
| 244 | end |
| 245 | end |
| 246 | |
| 247 | tY = tY - 1 |
| 248 | return true -- Turtle moved successfully |
| 249 | end |
| 250 | |
| 251 | local function goUp(bCheckFuel) |
| 252 | if bDebug then print("goUp()") end |
| 253 | |
| 254 | -- Can't move without fuel. checkFuel() will wait on player if necessary. |
| 255 | if (bCheckFuel==true or bCheckFuel==nil) then |
| 256 | checkFuel(tY>=0) -- Passes boolean true if moving away from 0,0,0 |
| 257 | end |
| 258 | |
| 259 | local tries = 3 |
| 260 | while not turtle.up() do |
| 261 | if bDebug then print("goUp: while not loop tries="..tries) end |
| 262 | if turtle.detectUp() then |
| 263 | if bDebug then print("goUp: detectUp") end |
| 264 | if not turtle.digUp() then |
| 265 | print("Undiggable block encountered. Will retry in 5 seconds.") |
| 266 | -- Turtle is blocked. In case this is a temporary glitch, we try 3 times before conceding hard failure |
| 267 | tries = tries - 1 |
| 268 | if (tries <= 0) then |
| 269 | return false |
| 270 | else |
| 271 | sleep(10) -- Wait 10 seconds, hope the problem resolves itself |
| 272 | end |
| 273 | end |
| 274 | elseif turtle.attackUp() then |
| 275 | if bDebug then print("goUp: attack") end |
| 276 | -- Had to attack player or mob. You can add additional code here such |
| 277 | -- as turtle.suck() if you want to collect killed mob loot. This is a quarry program |
| 278 | -- to collect ores, not rotten flesh and bones, so this block is empty. |
| 279 | else |
| 280 | -- Unknown obstruction, possibly a player in |
| 281 | -- peaceful or creative mode. Try again in 0.5 seconds and hope it's gone. |
| 282 | if bDebug then print("goUp: sleep(0.5)") end |
| 283 | sleep(0.5) |
| 284 | end |
| 285 | end |
| 286 | |
| 287 | tY = tY + 1 |
| 288 | return true -- Turtle moved successfully |
| 289 | end |
| 290 | |
| 291 | local function orient(targetXdir, targetZdir) |
| 292 | -- One of the supplied directions should be -1 or +1, the other should be 0. |
| 293 | if ((targetXdir ~= 0) and (targetZdir ~= 0)) or ((targetXdir==0) and (targetZdir==0)) then |
| 294 | print("orient() given mutually exclusive values: "..targetXdir..", "..targetZdir) |
| 295 | return false |
| 296 | end |
| 297 | |
| 298 | if (((targetXdir ~= 0) and (math.abs(targetXdir) ~= 1)) or ((targetZdir ~= 0) and (math.abs(targetZdir) ~= 1))) then |
| 299 | print("orient() given bad values: "..targetXdir..", "..targetZdir) |
| 300 | return false |
| 301 | end |
| 302 | |
| 303 | if (targetXdir ~= 0) and (targetXdir ~= xDir) then |
| 304 | -- x axis alignment requested, and differs from current alignment |
| 305 | if (xDir ~= 0) then |
| 306 | -- Turtle is x-axis aligned 180 from target |
| 307 | turnLeft() |
| 308 | turnLeft() |
| 309 | elseif (zDir == targetXdir) then |
| 310 | turnRight() |
| 311 | else |
| 312 | turnLeft() |
| 313 | end |
| 314 | elseif (targetZdir ~= 0) and (targetZdir ~= zDir) then |
| 315 | -- z axis alignment requested, and differs from current alignment |
| 316 | if (zDir ~= 0) then |
| 317 | -- Turtle is z-axis aligned 180 from target |
| 318 | turnLeft() |
| 319 | turnLeft() |
| 320 | elseif (xDir == targetZdir) then |
| 321 | turnLeft() |
| 322 | else |
| 323 | turnRight() |
| 324 | end |
| 325 | end |
| 326 | |
| 327 | return true |
| 328 | end |
| 329 | |
| 330 | local function goHome() |
| 331 | -- This is similar to moveTo(0,0,0) but axis ordering of movement is reversed, so that turtle takes |
| 332 | -- the same path to and from home location and where it left off. Also, this function passes false to |
| 333 | -- goDown, goUp and goForward to make them skip the per-move fuel check, because making that check |
| 334 | -- could result in circular function calling: goHome()->goFoward()->checkFuel()->goHome()->goFoward()->checkFuel().. etc. |
| 335 | -- This function is set up to move along Y-axis first, then X, then finally Z, unless bReverse is true |
| 336 | -- Note: The order doesn't matter much when digging out a space, but can matter when building something |
| 337 | -- so that you don't dig a tunnel through what you're building. |
| 338 | |
| 339 | local fuelNeeded = math.abs(tX)+math.abs(tY)+math.abs(tZ) |
| 340 | if not (turtle.getFuelLevel()>=fuelNeeded) then |
| 341 | print("Error: Turtle ended up in the unexpected state of not having enough fuel to return home.") |
| 342 | return false |
| 343 | end |
| 344 | |
| 345 | while (tY<0) do |
| 346 | if bDebug then print("goHome while tY<0 tY="..tY) end |
| 347 | if not goUp(false) then |
| 348 | -- Critical movement fail, bail |
| 349 | return false |
| 350 | end |
| 351 | end |
| 352 | |
| 353 | while (tY>0) do |
| 354 | if bDebug then print("goHome while tY>0 tY="..tY) end |
| 355 | if not goDown(false) then |
| 356 | -- Critical movement fail, bail |
| 357 | return false |
| 358 | end |
| 359 | end |
| 360 | |
| 361 | -- If not at tX==targetX, move the right direction until tX==targetX |
| 362 | if (tX>0) then orient(-1,0) end |
| 363 | if (tX<0) then orient(1,0) end |
| 364 | while (tX~=0) do |
| 365 | if bDebug then print("goHome while tX~=0 tX="..tX) end |
| 366 | if not goForward(false) then |
| 367 | -- Critical movement fail, bail |
| 368 | return false |
| 369 | end |
| 370 | end |
| 371 | |
| 372 | -- If not at tZ==targetZ, move the right direction until tZ==targetZ |
| 373 | if (tZ>0) then orient(0,-1) end |
| 374 | if (tZ<0) then orient(0,1) end |
| 375 | while (tZ~=0) do |
| 376 | if bDebug then print("goHome while tZ~=0 tZ="..tZ) end |
| 377 | if not goForward(false) then |
| 378 | -- Critical movement fail, bail |
| 379 | return false |
| 380 | end |
| 381 | end |
| 382 | |
| 383 | return true |
| 384 | end |
| 385 | |
| 386 | local function moveTo(targetX,targetZ,targetY) |
| 387 | |
| 388 | local fuelNeeded = math.abs(tX-targetX)+math.abs(tY-targetY)+math.abs(tZ-targetZ) |
| 389 | if not (turtle.getFuelLevel()>=fuelNeeded) then |
| 390 | print("Error: Turtle ended up in the unexpected state of not having enough fuel to return home.") |
| 391 | return false |
| 392 | end |
| 393 | |
| 394 | -- If not at tZ==targetZ, move the right direction until tZ==targetZ |
| 395 | if (tZ>targetZ) then orient(0,-1) end |
| 396 | if (tZ<targetZ) then orient(0,1) end |
| 397 | while (tZ~=targetZ) do |
| 398 | if bDebug then print("moveTo while tZ~=targetZ tZ="..tZ.." targetZ="..targetZ) end |
| 399 | if not goForward(false) then |
| 400 | -- Critical movement fail, bail |
| 401 | return false |
| 402 | end |
| 403 | end |
| 404 | |
| 405 | -- If not at tX==targetX, move the right direction until tX==targetX |
| 406 | if (tX>targetX) then orient(-1,0) end |
| 407 | if (tX<targetX) then orient(1,0) end |
| 408 | while (tX~=targetX) do |
| 409 | if bDebug then print("moveTo while tX~=targetX tX="..tX.." targetX="..targetX) end |
| 410 | if not goForward(false) then |
| 411 | -- Critical movement fail, bail |
| 412 | return false |
| 413 | end |
| 414 | end |
| 415 | |
| 416 | while (tY<targetY) do |
| 417 | if bDebug then print("moveTo while tY<targetY tY="..tY.." targetY="..targetY) end |
| 418 | if not goUp(false) then |
| 419 | -- Critical movement fail, bail |
| 420 | return false |
| 421 | end |
| 422 | end |
| 423 | |
| 424 | while (tY>targetY) do |
| 425 | if bDebug then print("moveTo while tY>targetY tY="..tY.." targetY="..targetY) end |
| 426 | if not goDown(false) then |
| 427 | -- Critical movement fail, bail |
| 428 | return false |
| 429 | end |
| 430 | end |
| 431 | |
| 432 | return true |
| 433 | end |
| 434 | |
| 435 | function goUnload(bNeedsFuel) |
| 436 | if bDebug then print("goUnload()") end |
| 437 | -- Save position and orientation |
| 438 | local saveX = tX |
| 439 | local saveZ = tZ |
| 440 | local saveY = tY |
| 441 | local saveXdir = xDir |
| 442 | local saveZdir = zDir |
| 443 | |
| 444 | if not goHome() then |
| 445 | -- Critical failure to move |
| 446 | return false |
| 447 | end |
| 448 | |
| 449 | orient(0,-1) |
| 450 | |
| 451 | -- Drop items. Turtle will not empty the slot designated as the refuel slot. |
| 452 | for i=1,16 do |
| 453 | if (i ~= refuelSlot) then |
| 454 | turtle.select(i) |
| 455 | turtle.drop() |
| 456 | end |
| 457 | end |
| 458 | |
| 459 | orient(0,1) |
| 460 | |
| 461 | -- Select first empty slot, might be a now-empty fuel slot, we don't really care |
| 462 | for i=1,16 do |
| 463 | if (turtle.getItemCount(i)==0) then |
| 464 | turtle.select(i) |
| 465 | break |
| 466 | end |
| 467 | end |
| 468 | |
| 469 | |
| 470 | -- Since we had to bring the turtle all the way home, calculate |
| 471 | -- the fuel needed to get back to where turtle left off mining, do at least one |
| 472 | -- full layer's worth of work, plus approximately enough to get back home again. It would be |
| 473 | -- silly to leave base with anything less than that, since the fuel would go nearly all to moving |
| 474 | -- the turtle through already-mined space doing no work... |
| 475 | local fuelNeeded = 2 * (math.abs(tX-saveX) + math.abs(tY-saveY) + math.abs(tZ-saveZ)) + (sizeX * sizeZ) |
| 476 | |
| 477 | while (turtle.getFuelLevel() < fuelNeeded) do |
| 478 | |
| 479 | if bDebug then print("Entering while true do in goUnload fuel check stage") end |
| 480 | |
| 481 | -- Scan inventory for fuel |
| 482 | local slot = 1 |
| 483 | turtle.select(slot) |
| 484 | local bRefueled = false |
| 485 | |
| 486 | while true do |
| 487 | if turtle.refuel(1) then |
| 488 | -- Found fuel in current slot, consume 1, see if it's enough, if not loop again |
| 489 | print("Consuming fuel item from slot "..slot) |
| 490 | if (turtle.getFuelLevel()>=fuelNeeded) then |
| 491 | print("Refueled from inventory, resuming quarrying...") |
| 492 | bRefueled = true |
| 493 | break |
| 494 | end |
| 495 | else |
| 496 | -- Couldn't refuel from currently-selected slot, try next slot. If there are no more slots, ask for player help. |
| 497 | if (slot < 16) then |
| 498 | slot = slot + 1 |
| 499 | turtle.select(slot) |
| 500 | else |
| 501 | -- There are no more slots to look in, reset selection so that we're ready to loop over all slots again, and so that the |
| 502 | slot = 1 |
| 503 | break |
| 504 | end |
| 505 | end |
| 506 | end |
| 507 | |
| 508 | if not bRefueled then |
| 509 | turtle.select(1) |
| 510 | print("Please add more fuel items to the turtle and press any key. Has:"..turtle.getFuelLevel().." Needs:"..fuelNeeded) |
| 511 | os.pullEvent("key") -- suspend code execution awaiting user keypress |
| 512 | end |
| 513 | end |
| 514 | |
| 515 | if not moveTo(saveX,saveZ,saveY) then |
| 516 | -- Critical failure to move |
| 517 | return false |
| 518 | end |
| 519 | |
| 520 | orient(saveXdir,saveZdir) |
| 521 | |
| 522 | return true |
| 523 | end |
| 524 | |
| 525 | local function checkFreeSlot() |
| 526 | -- This function will return true if the designated refuelSlot is empty, because if there is no fuel reserve there, there |
| 527 | -- is no reason not to allow item collection into this slot. |
| 528 | for i=1,16 do |
| 529 | if turtle.getItemCount(i)==0 then |
| 530 | return true |
| 531 | end |
| 532 | end |
| 533 | |
| 534 | -- Turtle does not have empty slot, goUnload |
| 535 | if not goUnload() then |
| 536 | return false |
| 537 | end |
| 538 | |
| 539 | return true |
| 540 | end |
| 541 | |
| 542 | --[[ |
| 543 | |
| 544 | START OF THE MAIN PROGRAM |
| 545 | |
| 546 | --]] |
| 547 | |
| 548 | checkFreeSlot() |
| 549 | |
| 550 | local abort = false |
| 551 | local traversal = 1 -- Counts x-z layers we're rasterizing. Used to determine turning directions at end of columns and layers |
| 552 | local lowestY = 1-sizeY |
| 553 | local bDigBelow, bDigAbove = false, false -- initially false |
| 554 | if bStartBelow then |
| 555 | if not goDown() then |
| 556 | print("Cannot dig below starting position. Aborting.") |
| 557 | return |
| 558 | end |
| 559 | tY = -1 |
| 560 | lowestY = -sizeY |
| 561 | end |
| 562 | while true do -- This loops digging layers |
| 563 | print("Main loop traversal="..traversal.." tY="..tY.." lowestY="..lowestY) |
| 564 | |
| 565 | local thisTraversal = traversal |
| 566 | if zSign == -1 then thisTraversal = traversal + 1 end |
| 567 | |
| 568 | if (traversal==1) then --special case since turtle initially starts NOT on a layer that it just dug out. |
| 569 | if ((tY - lowestY) == 0) then |
| 570 | bDigBelow, bDigAbove = false, false |
| 571 | elseif ((tY - lowestY) == 1) then |
| 572 | bDigBelow, bDigAbove = true, false |
| 573 | elseif ((tY - lowestY) >= 2) then |
| 574 | bDigBelow, bDigAbove = true, true |
| 575 | if not goDown() then |
| 576 | -- Turtle can't dig down, adjust lowestY because we can't go as deep as planned |
| 577 | lowestY = tY - 1 |
| 578 | end |
| 579 | else |
| 580 | -- Error: turtle is not in an expected place |
| 581 | print("Error: Turtle vertical position is not what we expect on 1st traversal. Aborting, please debug.") |
| 582 | abort = true |
| 583 | break |
| 584 | end |
| 585 | else |
| 586 | -- Not our first traversal, and turtle should now be on the last layer it dug out. |
| 587 | if ((tY - lowestY) == 1) then |
| 588 | bDigBelow, bDigAbove = true, false |
| 589 | elseif ((tY - lowestY) == 2) then |
| 590 | bDigBelow, bDigAbove = true, false |
| 591 | if not goDown() then |
| 592 | -- Turtle can't go down, adjust lowestY because we can't go as deep as planned |
| 593 | lowestY = tY - 1 |
| 594 | end |
| 595 | elseif ((tY - lowestY) >= 3) then |
| 596 | bDigBelow, bDigAbove = true, true |
| 597 | -- Try to descend 2, if either fails, adjust lowestY to just below where turtle is able to get to, and |
| 598 | -- cancel the need to digAbove |
| 599 | for j=1,2 do |
| 600 | if not goDown() then |
| 601 | -- Turtle can't dig down, adjust lowestY because we can't go as deep as planned |
| 602 | lowestY = tY - 1 |
| 603 | bDigAbove = false |
| 604 | end |
| 605 | end |
| 606 | else |
| 607 | -- Error: turtle is not in an expected place |
| 608 | print("Error: Turtle vertical position is not what we expect on traversal>1. Aborting, please debug.") |
| 609 | abort = true |
| 610 | break |
| 611 | end |
| 612 | end |
| 613 | |
| 614 | |
| 615 | |
| 616 | for column=1,sizeX do -- This loops sizeX times digging out columns |
| 617 | for block=1,(sizeZ-1) do -- this loops (sizeZ-1) times doing digDown and goForward to do all but the end of each column |
| 618 | |
| 619 | -- Since we're about to do a potentially ore-digging move, check for free space in inventory. |
| 620 | -- hasFreeSlot() calls goUnload if necessary |
| 621 | if not checkFreeSlot() then |
| 622 | print("Error: checkFreeSlot failure.") |
| 623 | abort = true |
| 624 | break |
| 625 | end |
| 626 | |
| 627 | if bDigBelow and turtle.detectDown() then |
| 628 | if not turtle.digDown() then |
| 629 | -- Turtle can't dig down, but we're not moving down so this is not a fatal error. |
| 630 | -- It might be bedrock below turtle, but that's not a concern until turtle is level with it. |
| 631 | end |
| 632 | end |
| 633 | |
| 634 | if bDigAbove and turtle.detectUp() then |
| 635 | if not turtle.digUp() then |
| 636 | -- Turtle can't dig up. This is actually concerning since we don't want to get him trapped under bedrock. |
| 637 | -- Because of the danger of entrapment, we're ending our quarrying here. |
| 638 | print("Turtle below undiggable block, backing out and returning home.") |
| 639 | myTurnRight() |
| 640 | myTurnRight() |
| 641 | if not goForward() then |
| 642 | -- This failure we care about, because there is something blocking us that we |
| 643 | -- can't dig, attack or otherwise resolve. Bust out of our digging loops and attempt to return home |
| 644 | print("Fatal Error during column goForward tX="..tX.." tZ="..tZ.." tY="..tY) |
| 645 | end |
| 646 | abort = true |
| 647 | break |
| 648 | end |
| 649 | sleep(0.5) -- wait to see if anything falls on turtle from above (sand, gravel) |
| 650 | |
| 651 | -- First dig up was successful, so we haven't got an undiggable block above, and undiggables can't fall, so we can |
| 652 | -- safely loop trying to dig up as long as something is falling on us (gravel, sand) |
| 653 | while turtle.detectUp() do |
| 654 | if bDebug then print("in while turtrle.detectUp() loop.") end |
| 655 | if not turtle.digUp() then |
| 656 | -- whatever is up there, we couldn't dig it, but it's not bedrock. Just move on... |
| 657 | break |
| 658 | end |
| 659 | sleep(0.5) |
| 660 | end |
| 661 | end |
| 662 | |
| 663 | if not goForward() then |
| 664 | -- This failure we care about, because there is something blocking us that we |
| 665 | -- can't dig, attack or otherwise resolve. Bust out of our digging loops and attempt to return home |
| 666 | -- after first checking to be sure the turtle is not under bedrock (if digging above) |
| 667 | print("Fatal Error during column goForward tX="..tX.." tZ="..tZ.." tY="..tY) |
| 668 | abort = true |
| 669 | break |
| 670 | end |
| 671 | end -- end of block loop |
| 672 | |
| 673 | -- If movement failed while traversing column, escape out, backing out from under bedrock if needed |
| 674 | if abort then |
| 675 | if bDigAbove and turtle.detectUp() then |
| 676 | if not turtle.digUp() then |
| 677 | -- Turtle can't dig up. This is actually concerning since we don't want to get him trapped under bedrock. |
| 678 | -- Because of the danger of entrapment, we're ending our quarrying here. |
| 679 | print("Turtle below undiggable block, backing out and returning home.") |
| 680 | myTurnRight() |
| 681 | myTurnRight() |
| 682 | if not goForward() then |
| 683 | -- This failure we care about, because there is something blocking us that we |
| 684 | -- can't dig, attack or otherwise resolve. Bust out of our digging loops and attempt to return home |
| 685 | print("Fatal Error during column goForward tX="..tX.." tZ="..tZ.." tY="..tY) |
| 686 | end |
| 687 | end |
| 688 | end |
| 689 | |
| 690 | -- unwinding |
| 691 | break |
| 692 | end |
| 693 | |
| 694 | -- Dig out the last block of this column |
| 695 | if bDigBelow and turtle.detectDown() then |
| 696 | if not turtle.digDown() then |
| 697 | -- Turtle can't dig down, but we're not moving down so this is not a fatal error. |
| 698 | -- It might be bedrock below turtle, but that's not a concern until turtle is level with it. |
| 699 | end |
| 700 | end |
| 701 | |
| 702 | -- Do last digUp in this column, if required by bDigAbove |
| 703 | if bDigAbove and turtle.detectUp() then |
| 704 | if not turtle.digUp() then |
| 705 | -- Turtle can't dig up. This is actually concerning since we don't want to get him trapped under bedrock. |
| 706 | -- Because of the danger of entrapment, we're ending our quarrying here. |
| 707 | print("Turtle below undiggable block, backing out and returning home.") |
| 708 | myTurnRight() |
| 709 | myTurnRight() |
| 710 | if not goForward() then |
| 711 | -- This failure we care about, because there is something blocking us that we |
| 712 | -- can't dig, attack or otherwise resolve. Bust out of our digging loops and attempt to return home |
| 713 | print("Fatal Error during column goForward tX="..tX.." tZ="..tZ.." tY="..tY) |
| 714 | end |
| 715 | abort = true |
| 716 | break |
| 717 | end |
| 718 | sleep(0.5) -- wait to see if anything falls on turtle from above (sand, gravel) |
| 719 | |
| 720 | -- First dig up was successful, so we haven't got an undiggable block above, and undiggables can't fall, so we can |
| 721 | -- safely loop trying to dig up as long as something is falling on us (gravel, sand) |
| 722 | while turtle.detectUp() do |
| 723 | if bDebug then print("in while turtrle.detectUp() loop.") end |
| 724 | if not turtle.digUp() then |
| 725 | -- whatever is up there, we couldn't dig it, but it's not bedrock. Just move on... |
| 726 | break |
| 727 | end |
| 728 | sleep(0.5) |
| 729 | end |
| 730 | end |
| 731 | |
| 732 | -- Turtle just finished the column, figure out if we need to advance to a new column, or |
| 733 | -- if we've finished the layer. If we need to turn to start a new column, we have to figure out which |
| 734 | -- direction to turn |
| 735 | if (column<sizeX) then |
| 736 | -- Turtle is at the end of a z column, but not the end of the whole x-z layer traversal |
| 737 | |
| 738 | -- FYI: These odd/even values are based on 1-based block, column, traversal numbers not 0-based tX, tZ, tY |
| 739 | -- sorry if that's confusing, but Lua convention is to start loop indicies at 1 |
| 740 | local evenCol = ((column%2)==0) |
| 741 | local evenWidth = ((sizeX%2)==0) |
| 742 | local evenLayer = ((thisTraversal%2)==0) |
| 743 | local backtrackingLayer = (evenWidth and evenLayer) |
| 744 | |
| 745 | if ((not evenCol and not backtrackingLayer) or (evenCol and backtrackingLayer)) then |
| 746 | if myTurnRight then |
| 747 | myTurnRight() -- turn towards next row |
| 748 | else |
| 749 | print("Error: myTurnRight is nil!") |
| 750 | turnRight() |
| 751 | end |
| 752 | if not goForward() then |
| 753 | print("Fatal Error during goForward from column "..column.." to column "..(column+1).." tX="..tX.." tZ="..tZ.." tY="..tY) |
| 754 | abort = true |
| 755 | break |
| 756 | end |
| 757 | |
| 758 | -- Danger check to see if we've moved under an undiggable block |
| 759 | if bDigAbove and turtle.detectUp() and not turtle.digUp() then |
| 760 | print("Turtle below undiggable block, backing out 1 and returning home.") |
| 761 | myTurnRight() |
| 762 | myTurnRight() |
| 763 | if not goForward() then |
| 764 | -- This failure we care about, because there is something blocking us that we |
| 765 | -- can't dig, attack or otherwise resolve. Bust out of our digging loops and attempt to return home |
| 766 | print("Fatal Error during column goForward tX="..tX.." tZ="..tZ.." tY="..tY) |
| 767 | end |
| 768 | abort = true |
| 769 | break |
| 770 | end |
| 771 | |
| 772 | myTurnRight() |
| 773 | else |
| 774 | myTurnLeft() |
| 775 | if not goForward() then |
| 776 | print("Fatal Error during goForward from column "..column.." to column "..(column+1).." tX="..tX.." tZ="..tZ.." tY="..tY) |
| 777 | abort = true |
| 778 | break |
| 779 | end |
| 780 | |
| 781 | -- Danger check to see if we've moved under an undiggable block |
| 782 | if bDigAbove and turtle.detectUp() and not turtle.digUp() then |
| 783 | print("Turtle below undiggable block, backing out 1 and returning home.") |
| 784 | myTurnRight() |
| 785 | myTurnRight() |
| 786 | if not goForward() then |
| 787 | -- This failure we care about, because there is something blocking us that we |
| 788 | -- can't dig, attack or otherwise resolve. Bust out of our digging loops and attempt to return home |
| 789 | print("Fatal Error during column goForward tX="..tX.." tZ="..tZ.." tY="..tY) |
| 790 | end |
| 791 | abort = true |
| 792 | break |
| 793 | end |
| 794 | |
| 795 | myTurnLeft() |
| 796 | end |
| 797 | -- Turtle is now ready to start the next column |
| 798 | else |
| 799 | -- Turtle is at the end of the layer, rotate 180 |
| 800 | myTurnRight() |
| 801 | myTurnRight() |
| 802 | end |
| 803 | end -- end of column loop |
| 804 | |
| 805 | if abort then |
| 806 | print("Abort breaking out of while true loop.") |
| 807 | -- abort in progress, unwinding out of loops |
| 808 | break |
| 809 | end |
| 810 | |
| 811 | -- See if we're done yet |
| 812 | if ((tY - lowestY) == 0) or (((tY - lowestY) == 1) and (bDigBelow == true)) then |
| 813 | -- We're done. We've finished digging our lowest layer either by digging forward or with digDown. |
| 814 | done = true |
| 815 | break |
| 816 | end |
| 817 | |
| 818 | -- If we got past the last if-then, we are not done, so we need to descend in preparation for next layer traversal |
| 819 | if bDigBelow then |
| 820 | -- We were digging below us on the traversal we just finished, so we need to drop down 2 levels to be on an undug layer |
| 821 | -- First we try to descend through the dug-down layer, but since that could have bedrock (we we skimming above it not caring) |
| 822 | -- we need to test to see if we can descend into that layer at our current tX,tZ location |
| 823 | if not goDown() then |
| 824 | print("Turtle finished a traversal and was digging below. Turtle can't go further down, we're done quarrying.") |
| 825 | abort = true |
| 826 | break |
| 827 | end |
| 828 | end |
| 829 | |
| 830 | traversal = traversal + 1 |
| 831 | end -- end of while not done loop |
| 832 | |
| 833 | -- Quarrying ended, either normally or because of encountering undiggable block. Try to return to 0,0,0 |
| 834 | if not goHome(0,0,0) then |
| 835 | -- Can't even get back home :-( Notify the user |
| 836 | print("Turtle was not able to safely get back to starting location") |
| 837 | abort = true |
| 838 | else |
| 839 | orient(0,-1) |
| 840 | |
| 841 | -- Drop everything |
| 842 | -- Drop items. Turtle will not empty the slot designated as the refuel slot. |
| 843 | print("Unloading all contents...") |
| 844 | for i=1,16 do |
| 845 | turtle.select(i) |
| 846 | turtle.drop() |
| 847 | end |
| 848 | orient(0,1) |
| 849 | end |
| 850 | |
| 851 | if abort then |
| 852 | print("Quarrying ended due to encounter with undiggable block.") |
| 853 | else |
| 854 | print("Quarrying complete to desired depth.") |
| 855 | end |
| 856 |