View difference between Paste ID: fhs7KzYn and MmuyL6Ma
SHOW: | | - or go back to the newest paste.
1
-- Advanced Mining Path Optimizer
2
-- Optimizes mining paths based on room dimensions to minimize turns
3
4
-- Position tracking
5
local currentX = 0
6-
local startRow = true -- Track if we're starting from the front or back of the row
6+
7-
local miningLength = 0  -- Store length as a module-level variable
7+
8-
local forward = true -- Moved to module-level to preserve state between layers
8+
9
local resumePos = {x=0, y=0, z=0, facing=0}
10
11
-- Essential items to keep
12-
    ["minecraft:torch"] = true  -- or a very high number like 9999
12+
13
    ["minecraft:torch"] = 64,
14
    ["minecraft:cobblestone"] = 128,
15-
local function setMiningLength(len)
15+
    ["minecraft:dirt"] = 128,
16-
  miningLength = len
16+
    ["minecraft:cobbled_deepslate"] = 128
17
}
18
19-
-- Utility functions
19+
-- Utility function to find an item in inventory
20
local function findItem(itemName)
21-
  for slot = 1, 16 do
21+
22
        local item = turtle.getItemDetail(slot)
23-
    if item and item.name == itemName then
23+
        if item and item.name == itemName then
24-
      turtle.select(slot)
24+
            turtle.select(slot)
25-
      return true
25+
            return true
26
        end
27-
  end
27+
28-
  return false
28+
29
end
30
31-
local function hasInventorySpace()
31+
-- Check if there's space in inventory
32-
  for slot = 1, 16 do
32+
local function hasSpace()
33-
    if turtle.getItemCount(slot) == 0 then
33+
34-
      return true
34+
35
            return true
36-
  end
36+
37-
  return false
37+
38
    return false
39
end
40-
local function turnToFacing(targetFacing)
40+
41-
  while facing ~= targetFacing do
41+
-- Handle liquid blocks by placing a solid block
42-
    turtle.turnRight()
42+
local function handleLiquid(direction)
43-
    facing = (facing + 1) % 4
43+
    if findItem("minecraft:cobblestone") or findItem("minecraft:dirt") or findItem("minecraft:cobbled_deepslate") then
44-
  end
44+
45
            turtle.placeUp()
46
        elseif direction == "down" then
47-
-- Optimized turning function that takes shortest path
47+
48
        else
49-
  local currentFacing = facing
49+
            turtle.place()
50-
  local rightTurns = (targetFacing - currentFacing) % 4
50+
51-
  local leftTurns = (currentFacing - targetFacing) % 4
51+
        sleep(0.5)
52-
  
52+
53-
  if rightTurns <= leftTurns then
53+
54-
      -- Turn right is shorter or equal
54+
55-
      for i = 1, rightTurns do
55+
56-
          turtle.turnRight()
56+
57-
          facing = (facing + 1) % 4
57+
-- Turn to face specific direction optimally
58-
      end
58+
59-
  else
59+
    local currentFacing = facing
60-
      -- Turn left is shorter
60+
    local rightTurns = (targetFacing - currentFacing) % 4
61-
      for i = 1, leftTurns do
61+
    local leftTurns = (currentFacing - targetFacing) % 4
62-
          turtle.turnLeft()
62+
63-
          facing = (facing - 1) % 4
63+
    if rightTurns <= leftTurns then
64-
      end
64+
        -- Turn right is shorter or equal
65-
  end
65+
        for i = 1, rightTurns do
66
            turtle.turnRight()
67
            facing = (facing + 1) % 4
68
        end
69
    else
70
        -- Turn left is shorter
71
        for i = 1, leftTurns do
72
            turtle.turnLeft()
73
            facing = (facing - 1) % 4
74
        end
75
    end
76-
        -- Check if there's a block in the way
76+
77-
        local detectFunc
77+
78
-- Try to move with obstacle handling
79-
            detectFunc = turtle.detectUp
79+
80
    -- First check if there's a liquid
81-
            detectFunc = turtle.detectDown
81+
    local detectFunc
82
    if direction == "up" then
83-
            detectFunc = turtle.detect
83+
        detectFunc = turtle.detectUp
84
    elseif direction == "down" then
85
        detectFunc = turtle.detectDown
86
    else
87-
            -- There's a block, dig it
87+
        detectFunc = turtle.detect
88-
            digFunc()
88+
89
90
    -- Maximum attempts to handle falling blocks
91
    local maxAttempts = 10
92
    local attempts = 0
93-
            -- No block, try to move
93+
94
    while attempts < maxAttempts do
95
        attempts = attempts + 1
96
        
97
        if detectFunc() then
98
            -- Handle liquid first
99-
        -- If we're still here after an attempt, brief pause
99+
            if handleLiquid(direction) then
100
                digFunc()
101
                if moveFunc() then
102
                    break
103-
            print("Warning: Unable to move after multiple attempts")
103+
                end
104
            else
105
                digFunc()
106
                if moveFunc() then
107
                    break
108
                end
109-
    if attempts < maxAttempts then
109+
110
        else
111
            if moveFunc() then
112
                break
113
            else
114
                -- If movement failed but no block detected, try handling liquid
115
                if handleLiquid(direction) then
116
                    if moveFunc() then
117
                        break
118
                    end
119
                end
120
            end
121
        end
122
123
        -- If we're still here after an attempt, brief pause before next try
124
        -- This helps with falling blocks settling
125
        sleep(0.2)
126-
-- Optimized turning function that takes shortest path
126+
127
        -- If we've tried several times and still can't move, it might be an infinite fall
128-
  local currentFacing = facing
128+
129-
  local rightTurns = (targetFacing - currentFacing) % 4
129+
            print("Warning: Possible falling blocks causing obstruction")
130-
  local leftTurns = (currentFacing - targetFacing) % 4
130+
131-
  
131+
132-
  if rightTurns <= leftTurns then
132+
133-
      -- Turn right is shorter or equal
133+
134-
      for i = 1, rightTurns do
134+
135-
          turtle.turnRight()
135+
    if attempts < maxAttempts then  -- Only update if we actually moved
136-
          facing = (facing + 1) % 4
136+
137-
      end
137+
138-
  else
138+
139-
      -- Turn left is shorter
139+
140-
      for i = 1, leftTurns do
140+
141-
          turtle.turnLeft()
141+
142-
          facing = (facing - 1) % 4
142+
143-
      end
143+
144-
  end
144+
145
        end
146
        return true
147
    end
148-
  local returnFacing = facing
148+
149-
  local pathFound = false
149+
150-
  
150+
151-
  -- Try multiple vertical levels to find an open path
151+
152-
  local function tryPathAtLevel(targetZ)
152+
-- Return to the chest position
153-
      -- Move to target Z level first
153+
154-
      while currentZ > targetZ do
154+
    local pathFound = false
155-
          if not turtle.down() then return false end
155+
156-
          currentZ = currentZ - 1
156+
    -- Try multiple vertical levels to find an open path
157-
      end
157+
    local function tryPathAtLevel(targetZ)
158-
      while currentZ < targetZ do
158+
        -- Move to target Z level first
159-
          if not turtle.up() then return false end
159+
        while currentZ > targetZ do
160-
          currentZ = currentZ + 1
160+
            if not turtle.down() then return false end
161-
      end
161+
162-
      
162+
163-
      -- Face toward chest (facing 2)
163+
        while currentZ < targetZ do
164-
      turnToFacingOptimal(2)
164+
            if not turtle.up() then return false end
165-
      
165+
166-
      -- Try Y movement without digging
166+
167-
      local initialY = currentY
167+
168-
      while currentY < 0 do
168+
        -- Face toward chest (facing 2)
169-
          if not turtle.forward() then
169+
        turnToFacingOptimal(2)
170-
              -- If blocked, restore position and return false
170+
171-
              while currentY < initialY do
171+
        -- Try Y movement without digging
172-
                  turtle.back()
172+
        local initialY = currentY
173-
                  currentY = currentY + 1
173+
        while currentY < 0 do
174-
              end
174+
            if not turtle.forward() then
175-
              return false
175+
                -- If blocked, restore position and return false
176-
          end
176+
                while currentY < initialY do
177-
          currentY = currentY + 1
177+
                    turtle.back()
178-
      end
178+
                    currentY = currentY + 1
179-
      
179+
                end
180-
      -- Try X movement without digging
180+
                return false
181-
      if currentX ~= 0 then
181+
182-
          if currentX > 0 then
182+
            currentY = currentY + 1
183-
              turnToFacingOptimal(3) -- face left
183+
184-
          else
184+
185-
              turnToFacingOptimal(1) -- face right
185+
        -- Try X movement without digging
186-
          end
186+
        if currentX ~= 0 then
187-
          
187+
            if currentX > 0 then
188-
          local initialX = currentX
188+
                turnToFacingOptimal(3) -- face left
189-
          while currentX ~= 0 do
189+
            else
190-
              if not turtle.forward() then
190+
                turnToFacingOptimal(1) -- face right
191-
                  -- If blocked, restore position and return false
191+
192-
                  while currentX ~= initialX do
192+
            
193-
                      turtle.back()
193+
            local initialX = currentX
194-
                      currentX = currentX + (currentX > 0 and 1 or -1)
194+
            while currentX ~= 0 do
195-
                  end
195+
                if not turtle.forward() then
196-
                  return false
196+
                    -- If blocked, restore position and return false
197-
              end
197+
                    while currentX ~= initialX do
198-
              currentX = currentX + (currentX > 0 and -1 or 1)
198+
                        turtle.back()
199-
          end
199+
                        currentX = currentX + (currentX > 0 and 1 or -1)
200-
      end
200+
                    end
201-
      
201+
                    return false
202-
      return true
202+
                end
203-
  end
203+
                currentX = currentX + (currentX > 0 and -1 or 1)
204-
  
204+
205-
  -- Try paths at different levels, starting with levels we expect to be clear
205+
206-
  local levelsToTry = {
206+
207-
      0,           -- Ground level (where chest is)
207+
208-
      -1,          -- One below ground
208+
209-
      1,           -- One above ground
209+
210-
      currentZ,    -- Current level
210+
    -- Try paths at different levels, starting with levels we expect to be clear
211-
  }
211+
    local levelsToTry = {
212-
  
212+
        0,           -- Ground level (where chest is)
213-
  -- Add intermediate levels if we're far from 0
213+
        -1,          -- One below ground
214-
  if math.abs(currentZ) > 1 then
214+
        1,           -- One above ground
215-
      table.insert(levelsToTry, math.floor(currentZ/2))
215+
        currentZ,    -- Current level
216-
  end
216+
    }
217-
  
217+
218-
  -- Try each level until we find a clear path
218+
    -- Add intermediate levels if we're far from 0
219-
  for _, targetZ in ipairs(levelsToTry) do
219+
    if math.abs(currentZ) > 1 then
220-
      if tryPathAtLevel(targetZ) then
220+
        table.insert(levelsToTry, math.floor(currentZ/2))
221-
          pathFound = true
221+
222-
          break
222+
223-
      end
223+
    -- Try each level until we find a clear path
224-
  end
224+
    for _, targetZ in ipairs(levelsToTry) do
225-
  
225+
        if tryPathAtLevel(targetZ) then
226-
  -- If no clear path found, fall back to original digging behavior
226+
            pathFound = true
227-
  if not pathFound then
227+
228-
      -- Original digging behavior
228+
229-
      while currentZ > 0 do
229+
230-
          if not tryMove(turtle.down, turtle.digDown, "down") then
230+
231-
              print("Can't move down to Z=0")
231+
    -- If no clear path found, fall back to original digging behavior
232-
              return false
232+
    if not pathFound then
233-
          end
233+
        -- Original digging behavior
234-
      end
234+
        while currentZ > 0 do
235-
      while currentZ < 0 do
235+
            if not tryMove(turtle.down, turtle.digDown, "down") then
236-
          if not tryMove(turtle.up, turtle.digUp, "up") then
236+
                print("Can't move down to Z=0")
237-
              print("Can't move up to Z=0")
237+
                return false
238-
              return false
238+
239-
          end
239+
240-
      end
240+
        while currentZ < 0 do
241-
      
241+
            if not tryMove(turtle.up, turtle.digUp, "up") then
242-
      turnToFacingOptimal(2)
242+
                print("Can't move up to Z=0")
243-
      while currentY < 0 do
243+
                return false
244-
          if not tryMove(turtle.forward, turtle.dig, "forward") then
244+
245-
              print("Obstruction while returning on Y axis")
245+
246-
              return false
246+
247-
          end
247+
        turnToFacingOptimal(2)
248-
      end
248+
        while currentY < 0 do
249-
      
249+
            if not tryMove(turtle.forward, turtle.dig, "forward") then
250-
      if currentX ~= 0 then
250+
                print("Obstruction while returning on Y axis")
251-
          if currentX > 0 then
251+
                return false
252-
              turnToFacingOptimal(3)
252+
253-
          else
253+
254-
              turnToFacingOptimal(1)
254+
255-
          end
255+
        if currentX ~= 0 then
256-
          
256+
            if currentX > 0 then
257-
          while currentX ~= 0 do
257+
                turnToFacingOptimal(3)
258-
              if not tryMove(turtle.forward, turtle.dig, "forward") then
258+
            else
259-
                  print("Obstruction while returning on X axis")
259+
                turnToFacingOptimal(1)
260-
                  return false
260+
261-
              end
261+
            
262-
          end
262+
            while currentX ~= 0 do
263-
      end
263+
                if not tryMove(turtle.forward, turtle.dig, "forward") then
264-
  end
264+
                    print("Obstruction while returning on X axis")
265-
  
265+
                    return false
266-
  -- Final position verification and facing correction
266+
                end
267-
  if currentX ~= 0 or currentY ~= 0 or currentZ ~= 0 then
267+
268-
      print("Failed to reach chest position!")
268+
269-
      return false
269+
270-
  end
270+
271-
  
271+
    -- Final position verification and facing correction
272-
  -- Ensure we're facing the chest (facing 2) at the end
272+
273-
  turnToFacingOptimal(2)
273+
        print("Failed to reach chest position!")
274-
  
274+
275-
  return true
275+
276
    
277
    -- Ensure we're facing the chest (facing 2) at the end
278-
local function hasEssentialItems()
278+
279-
    local hasTorches = false
279+
280
    return true
281
end
282
283
-- Dump inventory while preserving essential items
284-
            hasTorches = true
284+
285
    -- Store current position
286
    resumePos.x = currentX
287
    resumePos.y = currentY
288
    resumePos.z = currentZ
289-
    return hasTorches
289+
290
291
    -- Return to chest
292-
local function hasOperationalInventory()
292+
293-
    -- Check if we have at least 1 free slot AND torches
293+
294-
    local hasSpace = false
294+
295-
    local hasTorches = false
295+
    -- Track preserved quantities
296
    local preserved = {
297
        ["minecraft:torch"] = 0,
298
        ["minecraft:cobblestone"] = 0,
299-
            hasSpace = true
299+
        ["minecraft:dirt"] = 0,
300
        ["minecraft:cobbled_deepslate"] = 0
301-
            local item = turtle.getItemDetail(slot)
301+
    }
302-
            if item and item.name == "minecraft:torch" then
302+
303-
                hasTorches = true
303+
    -- First pass: Calculate total preserved items
304
    for slot = 1, 16 do
305
        local item = turtle.getItemDetail(slot)
306
        if item and ESSENTIAL_ITEMS[item.name] then
307
            preserved[item.name] = preserved[item.name] + item.count
308-
    return hasSpace and hasTorches
308+
309
    end
310
311
    -- Second pass: Drop excess items
312
    for slot = 1, 16 do
313
        turtle.select(slot)
314
        local item = turtle.getItemDetail(slot)
315
        
316
        if item then
317
            local itemName = item.name
318
            if ESSENTIAL_ITEMS[itemName] then
319
                local maxKeep = ESSENTIAL_ITEMS[itemName]
320
                local alreadyPreserved = preserved[itemName]
321
                
322
                if alreadyPreserved > maxKeep then
323-
    -- Simply drop all non-torch items
323+
                    -- Drop excess from this slot
324
                    local toDrop = math.min(alreadyPreserved - maxKeep, item.count)
325
                    turtle.drop(toDrop)
326
                    preserved[itemName] = preserved[itemName] - toDrop
327
                end
328-
        if item and item.name ~= "minecraft:torch" then
328+
            else
329-
            -- Drop all non-torch items
329+
                -- Drop all non-essential items
330-
            turtle.drop()
330+
                turtle.drop()
331
            end
332
        end
333
    end
334
335
    -- Return to mining position with optimized movement
336
    -- Move vertically first
337
    while currentZ ~= resumePos.z do
338
        if currentZ < resumePos.z then
339
            tryMove(turtle.up, turtle.digUp, "up")
340
        else
341
            tryMove(turtle.down, turtle.digDown, "down")
342
        end
343
    end
344
345
    -- Optimize Y movement
346
    if currentY ~= resumePos.y then
347
        if currentY > resumePos.y then
348
            turnToFacingOptimal(0)  -- Face mining direction
349
        else
350
            turnToFacingOptimal(2)  -- Face chest direction
351
        end
352
        while currentY ~= resumePos.y do
353
            tryMove(turtle.forward, turtle.dig, "forward")
354
        end
355
    end
356
357
    -- Optimize X movement
358
    if currentX ~= resumePos.x then
359
        if currentX < resumePos.x then
360
            turnToFacingOptimal(1)  -- Face right
361
        else
362
            turnToFacingOptimal(3)  -- Face left
363
        end
364
        while currentX ~= resumePos.x do
365
            tryMove(turtle.forward, turtle.dig, "forward")
366
        end
367
    end
368
369
    -- Return to original facing
370
    turnToFacingOptimal(resumePos.facing)
371
    return true
372
end
373
374
-- Dump all inventory at the end of mining
375
local function dumpAllInventory()
376
    -- Return to chest if not already there
377
    if currentX ~= 0 or currentY ~= 0 or currentZ ~= 0 then
378
        if not returnToChest() then
379
            print("Failed to return to chest!")
380
            return false
381
        end
382
    end
383
    
384
    -- Ensure facing chest
385
    turnToFacingOptimal(2)
386
    
387
    -- Small delay to ensure stable chest interaction
388
    sleep(0.5)
389
    
390
    -- Dump everything from inventory
391
    for slot = 1, 16 do
392
        turtle.select(slot)
393
        -- Drop entire stack, regardless of item type
394
        turtle.drop()
395
    end
396
    
397
    return true
398-
-- Calculate torch positions for symmetric placement
398+
399-
local function calculateTorchPositions(length, width)
399+
400-
  local positions = {}
400+
-- Calculate required torches
401-
  
401+
402-
  -- For very small rooms (less than 7x7), just place a torch in the center
402+
    return math.ceil(length/4) * math.ceil(width/4)
403-
  if length <= 7 and width <= 7 then
403+
404-
    table.insert(positions, {x = math.ceil(length/2), z = math.ceil(width/2)})
404+
405-
    return positions
405+
-- Move vertically based on direction
406-
  end
406+
local function moveVertical(verticalDir)
407-
  
407+
    if verticalDir == "up" then
408-
  -- For larger rooms, create a grid of torches with optimal spacing
408+
        return turtle.up, turtle.digUp, "up"
409-
  -- In newer versions (1.18+), we can use spacing up to 13 blocks
409+
410-
  -- But we'll adjust for symmetry based on room dimensions
410+
        return turtle.down, turtle.digDown, "down"
411-
  
411+
412-
  -- Calculate spacing for symmetrical pattern
412+
413-
  local xSpacing = math.min(13, length)
413+
414-
  local zSpacing = math.min(13, width)
414+
-- Execute the generated path
415-
  
415+
local function executePath(path)
416-
  -- Adjust spacing for larger rooms to maintain symmetry
416+
    local torchCounter = 0
417-
  if length > 13 then
417+
418-
    -- Find the number of torches needed along length
418+
    for i, step in ipairs(path) do
419-
    local numTorchesX = math.ceil(length / 13)
419+
        -- Check inventory space
420-
    -- Distribute evenly
420+
        if not hasSpace() then
421-
    xSpacing = length / numTorchesX
421+
            if not dumpInventory() then
422-
  end
422+
                print("Aborting mining operation")
423-
  
423+
                return false
424-
  if width > 13 then
424+
425-
    -- Find the number of torches needed along width
425+
426-
    local numTorchesZ = math.ceil(width / 13)
426+
427-
    -- Distribute evenly
427+
        if step.action == "mine" then
428-
    zSpacing = width / numTorchesZ
428+
            -- Mine and move forward
429-
  end
429+
            if not tryMove(turtle.forward, turtle.dig, "forward") then
430-
  
430+
                print("Obstruction detected at position " .. step.x .. "," .. step.y)
431-
  -- Calculate offsets to center the grid
431+
                return false
432-
  local xOffset = xSpacing / 2
432+
433-
  local zOffset = zSpacing / 2
433+
            
434-
  
434+
            -- Place torch periodically
435-
  -- Create the grid of torch positions
435+
            torchCounter = torchCounter + 1
436-
  for x = xOffset, length, xSpacing do
436+
            if torchCounter % 4 == 0 and findItem("minecraft:torch") then
437-
    for z = zOffset, width, zSpacing do
437+
                turtle.placeDown()
438-
      table.insert(positions, {x = math.floor(x), z = math.floor(z)})
438+
439
        elseif step.action == "turn_right" then
440-
  end
440+
            turtle.turnRight()
441-
  
441+
            facing = (facing + 1) % 4
442-
  return positions
442+
        elseif step.action == "turn_left" then
443
            turtle.turnLeft()
444
            facing = (facing - 1) % 4
445-
-- Calculate the total number of torches needed
445+
446
    end
447-
  local positions = calculateTorchPositions(length, width)
447+
448-
  return #positions
448+
449
end
450
451
-- Generate an improved serpentine pattern for even×even dimensions
452
local function generateSerpentinePath(length, width)
453
    local path = {}
454-
  print("Usage: digRoom <length> <width> <height> [horizontal] [vertical]")
454+
455-
  print("horizontal: left/right (default: right)")
455+
    -- Start at position 1,1
456-
  print("vertical: up/down (default: up)")
456+
    table.insert(path, {x=1, y=1, action="mine"})
457-
  return
457+
458
    for row = 1, width do
459
        local isEvenRow = (row % 2 == 0)
460
        
461
        for col = 2, length do
462
            local x = isEvenRow and (length - col + 1) or col
463
            table.insert(path, {x=x, y=row, action="mine"})
464
        end
465
        
466-
setMiningLength(length)
466+
        -- Move to next row if not the last row
467
        if row < width then
468
            local x = isEvenRow and 1 or length
469-
  print("Invalid dimensions!")
469+
            -- Add turn
470-
  return
470+
            table.insert(path, {x=x, y=row, action="turn_right"})
471
            -- Add move down
472
            table.insert(path, {x=x, y=row+1, action="mine"})
473
            -- Add turn to prepare for next row
474-
  print("Invalid horizontal direction! Use 'left' or 'right'")
474+
            if isEvenRow then
475-
  return
475+
                table.insert(path, {x=x, y=row+1, action="turn_right"})
476
            else
477
                table.insert(path, {x=x, y=row+1, action="turn_left"})
478
            end
479-
  print("Invalid vertical direction! Use 'up' or 'down'")
479+
480-
  return
480+
481
    
482
    return path
483
end
484
485-
local fuelNeeded = totalBlocks + height + math.ceil(width/2) * 2
485+
-- Generate a spiral pattern for odd×odd dimensions
486
local function generateSpiralPath(length, width)
487
    local path = {}
488
    local x, y = 1, 1
489
    local minX, maxX = 1, length
490-
  print(string.format("Need %d fuel, have %d", fuelNeeded, turtle.getFuelLevel()))
490+
    local minY, maxY = 1, width
491-
  return
491+
    local dir = 0  -- 0=right, 1=down, 2=left, 3=up
492
    
493
    -- Track visited blocks
494
    local visited = {}
495
    for i = 1, length do
496-
  local torchCount = 0
496+
        visited[i] = {}
497-
  for slot = 1, 16 do
497+
        for j = 1, width do
498
            visited[i][j] = false
499-
    if item and item.name == "minecraft:torch" then
499+
500-
      torchCount = torchCount + turtle.getItemCount(slot)
500+
501
    
502-
  end
502+
    visited[x][y] = true
503-
  if torchCount < requiredTorches then
503+
    table.insert(path, {x=x, y=y, action="mine"})
504-
    print(string.format("Need %d torches, have %d", requiredTorches, torchCount))
504+
505
    while true do
506-
  end
506+
        local nextX, nextY = x, y
507
        
508
        if dir == 0 then  -- right
509-
local function turnToDir(targetDir)
509+
            nextX = x + 1
510-
  if horizontalDir == "left" then
510+
            if nextX > maxX or visited[nextX][y] then
511-
    if targetDir == "right" then
511+
                dir = (dir + 1) % 4
512-
      turtle.turnLeft()
512+
                minY = minY + 1
513-
      facing = (facing - 1) % 4
513+
                nextX, nextY = x, y + 1
514
            end
515-
      turtle.turnRight()
515+
        elseif dir == 1 then  -- down
516-
      facing = (facing + 1) % 4
516+
            nextY = y + 1
517
            if nextY > maxY or visited[x][nextY] then
518-
  else
518+
                dir = (dir + 1) % 4
519-
    if targetDir == "right" then
519+
                maxX = maxX - 1
520-
      turtle.turnRight()
520+
                nextX, nextY = x - 1, y
521-
      facing = (facing + 1) % 4
521+
522
        elseif dir == 2 then  -- left
523-
      turtle.turnLeft()
523+
            nextX = x - 1
524-
      facing = (facing - 1) % 4
524+
            if nextX < minX or visited[nextX][y] then
525
                dir = (dir + 1) % 4
526-
  end
526+
                maxY = maxY - 1
527
                nextX, nextY = x, y - 1
528
            end
529-
local function moveVertical()
529+
        else  -- up
530-
  if verticalDir == "up" then
530+
            nextY = y - 1
531-
    return turtle.up, turtle.digUp, "up"
531+
            if nextY < minY or visited[x][nextY] then
532-
  else
532+
                dir = (dir + 1) % 4
533-
    return turtle.down, turtle.digDown, "down"
533+
                minX = minX + 1
534-
  end
534+
                nextX, nextY = x + 1, y
535
            end
536
        end
537-
local function mineLayer()
537+
538-
  -- Calculate torch positions for this layer
538+
        -- Add turn if direction changed
539-
  local torchPositions = calculateTorchPositions(length, width)
539+
        if x ~= nextX or y ~= nextY then
540-
  
540+
            if nextX < 1 or nextX > length or nextY < 1 or nextY > width or visited[nextX][nextY] then
541-
  -- Initialize room-relative coordinates
541+
                -- We've completed the spiral
542-
  local roomX = 0
542+
543-
  local roomZ = 0
543+
544-
  
544+
            
545-
  for row = 1, width do
545+
            -- Add turn if needed
546-
    roomZ = row - 1  -- Z coordinate is the row (0-indexed)
546+
            if dir == 0 and facing ~= 1 then
547
                table.insert(path, {x=x, y=y, action="turn_right"})
548-
    for col = 1, length - 1 do
548+
            elseif dir == 1 and facing ~= 2 then
549-
      -- Update room X based on direction (serpentine pattern)
549+
                table.insert(path, {x=x, y=y, action="turn_right"})
550-
      if forward then
550+
            elseif dir == 2 and facing ~= 3 then
551-
        roomX = col - 1  -- When mining forward, X increases
551+
                table.insert(path, {x=x, y=y, action="turn_right"})
552-
      else
552+
            elseif dir == 3 and facing ~= 0 then
553-
        roomX = length - col  -- When mining backward, X decreases
553+
                table.insert(path, {x=x, y=y, action="turn_right"})
554-
      end
554+
555-
      
555+
            
556-
      -- Check if current room position should have a torch with exact matching
556+
            -- Add move
557-
      for _, pos in ipairs(torchPositions) do
557+
            table.insert(path, {x=nextX, y=nextY, action="mine"})
558-
        if pos.x - 1 == roomX and pos.z - 1 == roomZ then
558+
            visited[nextX][nextY] = true
559-
          if findItem("minecraft:torch") then
559+
            x, y = nextX, nextY
560-
            print("Placing torch at room position: " .. roomX .. "," .. roomZ)
560+
561
            -- No more moves possible
562
            break
563-
          end
563+
564
    end
565-
      end
565+
566-
      
566+
    return path
567-
      -- Continue with inventory check and movement
567+
568-
      local hasSpace = false
568+
569-
      for slot = 1, 16 do
569+
-- Generate an adaptive pattern for mixed dimensions (odd×even or even×odd)
570
local function generateAdaptivePath(length, width)
571-
          hasSpace = true
571+
    local path = {}
572-
          break
572+
573
    -- Start at position 1,1
574-
      end
574+
    table.insert(path, {x=1, y=1, action="mine"})
575-
      
575+
576-
      if not hasSpace then
576+
    for row = 1, width do
577-
        if not dumpInventory() then
577+
        local isEvenRow = (row % 2 == 0)
578-
          print("Aborting mining operation")
578+
579-
          return false
579+
        for col = 2, length do
580
            local x = isEvenRow and (length - col + 1) or col
581-
      end
581+
            table.insert(path, {x=x, y=row, action="mine"})
582-
      
582+
583-
      -- Move forward
583+
584-
      if not tryMove(turtle.forward, turtle.dig, "forward") then
584+
        -- Move to next row if not the last row
585-
        print("Obstruction detected")
585+
        if row < width then
586
            local x = isEvenRow and 1 or length
587-
      end
587+
            -- Add turn
588
            table.insert(path, {x=x, y=row, action="turn_right"})
589
            -- Add move down
590-
    -- Handle row changes
590+
            table.insert(path, {x=x, y=row+1, action="mine"})
591-
    if row < width then
591+
            -- Add turn to prepare for next row
592-
      if forward then
592+
            if isEvenRow then
593-
        turnToDir("right")
593+
                table.insert(path, {x=x, y=row+1, action="turn_right"})
594-
        if not tryMove(turtle.forward, turtle.dig, "forward") then return false end
594+
            else
595-
        turnToDir("right")
595+
                table.insert(path, {x=x, y=row+1, action="turn_left"})
596-
      else
596+
597-
        turnToDir("left")
597+
598-
        if not tryMove(turtle.forward, turtle.dig, "forward") then return false end
598+
599-
        turnToDir("left")
599+
600-
      end
600+
    -- Add optimized return path for mixed dimensions
601-
      forward = not forward
601+
    -- This is particularly important for odd×even dimensions
602
    if width % 2 == 0 then
603-
  end
603+
        -- We ended at the bottom left, which is good for returning
604
        -- No need to optimize
605-
  return true
605+
606
        -- We ended at the bottom right, optimize return path
607
        local endPos = path[#path]
608-
-- Modified end of main program
608+
        if endPos.x == length and endPos.y == width then
609
            -- Add path to get closer to start
610
            table.insert(path, {x=length, y=width, action="turn_left"})
611-
        forward = (layer % 2 == 1)
611+
            table.insert(path, {x=length, y=width, action="turn_left"})
612
            
613-
        forward = true
613+
            -- Move up a few steps
614
            for i = 1, math.min(3, width-1) do
615
                table.insert(path, {x=length, y=width-i, action="mine"})
616-
    if not mineLayer() then break end
616+
617-
  
617+
            
618
            -- Turn left toward start
619-
        -- Move up/down
619+
            table.insert(path, {x=length, y=width-3, action="turn_left"})
620-
        local moveFunc, digFunc, direction = moveVertical()
620+
            
621
            -- Move left a few steps
622
            for i = 1, math.min(3, length-1) do
623
                table.insert(path, {x=length-i, y=width-3, action="mine"})
624
            end
625
        end
626
    end
627
    
628
    return path
629
end
630-
        -- Turn around for next layer
630+
631-
        turtle.turnRight()
631+
-- Generate a specialized pattern for mining a chunk (16×16 or larger)
632-
        turtle.turnRight()
632+
local function generateChunkPattern(length, width)
633-
        facing = (facing + 2) % 4
633+
    local path = {}
634
    
635
    -- Calculate quadrant sizes
636
    local quadWidth = math.floor(width / 2)
637
    local quadLength = math.floor(length / 2)
638
    
639
    -- First quadrant (top-left)
640
    local q1 = generateSerpentinePath(quadLength, quadWidth)
641
    for _, move in ipairs(q1) do
642
        table.insert(path, move)
643
    end
644
    
645
    -- Add bridge to second quadrant (top-right)
646
    local lastPos = q1[#q1]
647
    if not lastPos then
648
        -- Error handling if q1 is empty (should not happen)
649
        print("Error: Failed to generate path for first quadrant")
650
        return generateSerpentinePath(length, width) -- Fallback to simple pattern
651
    end
652
    
653
    table.insert(path, {x=lastPos.x, y=lastPos.y, action="turn_right"})
654
    
655
    -- Move to second quadrant
656
    for i = 1, (length - lastPos.x) do
657
        table.insert(path, {x=lastPos.x + i, y=lastPos.y, action="mine"})
658
    end
659
    
660
    -- Second quadrant (top-right)
661
    local q2 = generateSerpentinePath(quadLength, quadWidth)
662
    for _, move in ipairs(q2) do
663
        -- Adjust coordinates for this quadrant
664
        local adjusted = {
665
            x = move.x + quadLength,
666
            y = move.y,
667
            action = move.action
668
        }
669
        table.insert(path, adjusted)
670
    end
671
    
672
    -- Add bridge to third quadrant (bottom-right)
673
    local lastPos2 = {x = q2[#q2].x + quadLength, y = q2[#q2].y}
674
    table.insert(path, {x=lastPos2.x, y=lastPos2.y, action="turn_right"})
675
    
676
    -- Move to third quadrant
677
    for i = 1, (width - lastPos2.y) do
678
        table.insert(path, {x=lastPos2.x, y=lastPos2.y + i, action="mine"})
679
    end
680
    
681
    -- Third quadrant (bottom-right)
682
    local q3 = generateSerpentinePath(quadLength, quadWidth)
683
    for _, move in ipairs(q3) do
684
        -- Adjust coordinates for this quadrant
685
        local adjusted = {
686
            x = move.x + quadLength,
687
            y = move.y + quadWidth,
688
            action = move.action
689
        }
690
        table.insert(path, adjusted)
691
    end
692
    
693
    -- Add bridge to fourth quadrant (bottom-left)
694
    local lastPos3 = {x = q3[#q3].x + quadLength, y = q3[#q3].y + quadWidth}
695
    table.insert(path, {x=lastPos3.x, y=lastPos3.y, action="turn_right"})
696
    
697
    -- Move to fourth quadrant
698
    for i = 1, (lastPos3.x - 1) do
699
        table.insert(path, {x=lastPos3.x - i, y=lastPos3.y, action="mine"})
700
    end
701
    
702
    -- Fourth quadrant (bottom-left)
703
    local q4 = generateSerpentinePath(quadLength, quadWidth)
704
    for _, move in ipairs(q4) do
705
        -- Adjust coordinates for this quadrant
706
        local adjusted = {
707
            x = move.x,
708
            y = move.y + quadWidth,
709
            action = move.action
710
        }
711
        table.insert(path, adjusted)
712
    end
713
    
714
    return path
715
end
716
717
-- Generate path for a square or rectangular room
718
local function generatePath(length, width)
719
    local path = {}
720
    
721
    -- Determine the best path strategy based on dimensions
722
    if length == width and length % 2 == 1 then
723
        -- Square with odd dimensions - use spiral
724
        print("Using spiral pattern for square with odd dimensions")
725
        return generateSpiralPath(length, width)
726
    elseif length >= 16 and width >= 16 then
727
        -- Large area (chunk size) - use chunk pattern
728
        print("Using optimized chunk mining pattern")
729
        return generateChunkPattern(length, width)
730
    elseif length % 2 == 0 and width % 2 == 0 then
731
        -- Even x Even - use serpentine
732
        print("Using improved serpentine for even×even dimensions")
733
        return generateSerpentinePath(length, width)
734
    else
735
        -- Mixed dimensions - use adaptive pattern
736
        print("Using adaptive pattern for mixed dimensions")
737
        return generateAdaptivePath(length, width)
738
    end
739
end
740
741
-- Main Program
742
local args = {...}
743
if #args < 3 then
744
    print("Usage: digRoom <length> <width> <height> [horizontal] [vertical]")
745
    print("horizontal: left/right (default: right)")
746
    print("vertical: up/down (default: up)")
747
    return
748
end
749
750
local length = tonumber(args[1])
751
local width = tonumber(args[2])
752
local height = tonumber(args[3])
753
local horizontalDir = args[4] or "right"
754
local verticalDir = args[5] or "up"
755
756
if not (length and width and height) or length < 1 or width < 1 or height < 1 then
757
    print("Invalid dimensions!")
758
    return
759
end
760
761
if horizontalDir ~= "left" and horizontalDir ~= "right" then
762
    print("Invalid horizontal direction! Use 'left' or 'right'")
763
    return
764
end
765
766
if verticalDir ~= "up" and verticalDir ~= "down" then
767
    print("Invalid vertical direction! Use 'up' or 'down'")
768
    return
769
end
770
771
-- Calculate required resources
772
local totalBlocks = length * width * height
773
-- Add extra margin for fuel based on path complexity
774
local fuelNeeded = totalBlocks * 1.2
775
local requiredTorches = height > 1 and calculateTorches(length, width) or 0
776
777
-- Check fuel
778
if turtle.getFuelLevel() < fuelNeeded then
779
    print(string.format("Need %d fuel, have %d", fuelNeeded, turtle.getFuelLevel()))
780
    return
781
end
782
783
-- Check torches if needed
784
if requiredTorches > 0 then
785
    local torchCount = 0
786
    for slot = 1, 16 do
787
        local item = turtle.getItemDetail(slot)
788
        if item and item.name == "minecraft:torch" then
789
            torchCount = torchCount + turtle.getItemCount(slot)
790
        end
791
    end
792
    if torchCount < requiredTorches then
793
        print(string.format("Need %d torches, have %d", requiredTorches, torchCount))
794
        return
795
    end
796
end
797
798
-- Check for blocking material
799
local hasBlockingMaterial = false
800
for slot = 1, 16 do
801
    local item = turtle.getItemDetail(slot)
802
    if item and (item.name == "minecraft:cobblestone" or item.name == "minecraft:dirt" or item.name == "minecraft:cobbled_deepslate") then
803
        hasBlockingMaterial = true
804
        break
805
    end
806
end
807
808
if not hasBlockingMaterial then
809
    print("Warning: No blocks available for liquid handling")
810
    print("Recommend having cobblestone, dirt, or cobbled deepslate")
811
    print("Continue anyway? (y/n)")
812
    local response = read():lower()
813
    if response ~= "y" then
814
        return
815
    end
816
end
817
818
print(string.format("Mining room %d×%d×%d using optimized algorithm", length, width, height))
819
820
-- Mine each layer
821
for layer = 1, height do
822
    print("Mining layer " .. layer .. " of " .. height)
823
    
824
    -- Generate optimized path for this layer
825
    local path = generatePath(length, width)
826
    
827
    -- Execute the path
828
    if not executePath(path) then
829
        print("Mining operation aborted at layer " .. layer)
830
        break
831
    end
832
    
833
    if layer < height then
834
        -- Move up/down to next layer
835
        local moveFunc, digFunc, direction = moveVertical(verticalDir)
836
        if not tryMove(moveFunc, digFunc, direction) then
837
            print("Warning: Unable to move " .. verticalDir .. " (possible liquid)")
838
            print("Try again? (y/n)")
839
            local response = read():lower()
840
            if response ~= "y" then
841
                break
842
            end
843
        end
844
    end
845
end
846
847
-- Final return and dump all inventory
848
print("Mining complete! Returning to chest...")
849
if dumpAllInventory() then
850
    print("All items deposited in chest.")
851
    turnToFacingOptimal(0)
852
else
853
    print("Failed to deposit all items!")
854
end