inital commit
This commit is contained in:
611
turtle.lua
Normal file
611
turtle.lua
Normal file
@@ -0,0 +1,611 @@
|
||||
-- Advanced Autonomous Mining Turtle (FIXED v3)
|
||||
-- Features: GPS tracking, auto-mining, fuel management, smart navigation
|
||||
|
||||
local CHANNEL_RECEIVE = 100
|
||||
local CHANNEL_SEND = 101
|
||||
local STATUS_CHANNEL = 102
|
||||
|
||||
-- State management
|
||||
local state = {
|
||||
mode = "idle", -- idle, manual, exploring, mining, returning
|
||||
position = nil,
|
||||
homePosition = nil,
|
||||
fuel = 0,
|
||||
inventory = {},
|
||||
target = nil,
|
||||
path = {},
|
||||
lastStatusUpdate = 0,
|
||||
stuckCounter = 0
|
||||
}
|
||||
|
||||
-- Configuration
|
||||
local config = {
|
||||
minFuelToReturn = 500,
|
||||
minFuelToExplore = 1000,
|
||||
statusUpdateInterval = 5, -- seconds
|
||||
maxStuckAttempts = 3,
|
||||
valuableBlocks = {
|
||||
["minecraft:coal_ore"] = 1,
|
||||
["minecraft:iron_ore"] = 2,
|
||||
["minecraft:gold_ore"] = 3,
|
||||
["minecraft:diamond_ore"] = 5,
|
||||
["minecraft:emerald_ore"] = 5,
|
||||
["minecraft:redstone_ore"] = 2,
|
||||
["minecraft:lapis_ore"] = 2,
|
||||
["minecraft:deepslate_coal_ore"] = 1,
|
||||
["minecraft:deepslate_iron_ore"] = 2,
|
||||
["minecraft:deepslate_gold_ore"] = 3,
|
||||
["minecraft:deepslate_diamond_ore"] = 5,
|
||||
["minecraft:deepslate_emerald_ore"] = 5,
|
||||
["minecraft:deepslate_redstone_ore"] = 2,
|
||||
["minecraft:deepslate_lapis_ore"] = 2,
|
||||
}
|
||||
}
|
||||
|
||||
-- Check for modem
|
||||
local modem = peripheral.find("modem")
|
||||
if not modem then
|
||||
error("No wireless modem found!")
|
||||
end
|
||||
modem.open(CHANNEL_RECEIVE)
|
||||
|
||||
print("Advanced Mining Turtle System")
|
||||
print("ID: " .. os.getComputerID())
|
||||
|
||||
-- GPS Functions
|
||||
local function updatePosition()
|
||||
local x, y, z = gps.locate(2)
|
||||
if x then
|
||||
state.position = {x = math.floor(x), y = math.floor(y), z = math.floor(z)}
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function setHome()
|
||||
if updatePosition() then
|
||||
state.homePosition = {
|
||||
x = state.position.x,
|
||||
y = state.position.y,
|
||||
z = state.position.z
|
||||
}
|
||||
print("Home set at: " .. state.homePosition.x .. ", " .. state.homePosition.y .. ", " .. state.homePosition.z)
|
||||
return true
|
||||
end
|
||||
print("Failed to get GPS position for home")
|
||||
return false
|
||||
end
|
||||
|
||||
-- Movement tracking
|
||||
local facing = 0 -- 0=North(Z-), 1=East(X+), 2=South(Z+), 3=West(X-)
|
||||
|
||||
local function updateFacingAfterTurn(right)
|
||||
if right then
|
||||
facing = (facing + 1) % 4
|
||||
else
|
||||
facing = (facing - 1) % 4
|
||||
end
|
||||
end
|
||||
|
||||
local function smartForward()
|
||||
local success = turtle.forward()
|
||||
if success and state.position then
|
||||
if facing == 0 then state.position.z = state.position.z - 1
|
||||
elseif facing == 1 then state.position.x = state.position.x + 1
|
||||
elseif facing == 2 then state.position.z = state.position.z + 1
|
||||
elseif facing == 3 then state.position.x = state.position.x - 1
|
||||
end
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
local function smartBack()
|
||||
local success = turtle.back()
|
||||
if success and state.position then
|
||||
if facing == 0 then state.position.z = state.position.z + 1
|
||||
elseif facing == 1 then state.position.x = state.position.x - 1
|
||||
elseif facing == 2 then state.position.z = state.position.z - 1
|
||||
elseif facing == 3 then state.position.x = state.position.x + 1
|
||||
end
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
local function smartUp()
|
||||
local success = turtle.up()
|
||||
if success and state.position then
|
||||
state.position.y = state.position.y + 1
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
local function smartDown()
|
||||
local success = turtle.down()
|
||||
if success and state.position then
|
||||
state.position.y = state.position.y - 1
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
local function smartTurnRight()
|
||||
local success = turtle.turnRight()
|
||||
if success then
|
||||
updateFacingAfterTurn(true)
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
local function smartTurnLeft()
|
||||
local success = turtle.turnLeft()
|
||||
if success then
|
||||
updateFacingAfterTurn(false)
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
-- Fuel management
|
||||
local function updateFuel()
|
||||
state.fuel = turtle.getFuelLevel()
|
||||
return state.fuel
|
||||
end
|
||||
|
||||
local function needsRefuel()
|
||||
return state.fuel ~= "unlimited" and state.fuel < config.minFuelToReturn
|
||||
end
|
||||
|
||||
local function tryRefuel()
|
||||
for slot = 1, 16 do
|
||||
turtle.select(slot)
|
||||
if turtle.refuel(0) then -- Check if it's fuel
|
||||
local count = turtle.getItemCount()
|
||||
if count > 0 then
|
||||
turtle.refuel(1)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Inventory management
|
||||
local function updateInventory()
|
||||
state.inventory = {}
|
||||
for slot = 1, 16 do
|
||||
local item = turtle.getItemDetail(slot)
|
||||
if item then
|
||||
table.insert(state.inventory, {
|
||||
slot = slot,
|
||||
name = item.name,
|
||||
count = item.count
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function inventoryFull()
|
||||
for slot = 1, 16 do
|
||||
if turtle.getItemCount(slot) == 0 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function isValuableBlock(blockName)
|
||||
return config.valuableBlocks[blockName] ~= nil
|
||||
end
|
||||
|
||||
-- Check if block is unbreakable
|
||||
local function isUnbreakable(blockName)
|
||||
if not blockName then return false end
|
||||
return string.find(blockName, "bedrock") or string.find(blockName, "barrier")
|
||||
end
|
||||
|
||||
-- Mining functions
|
||||
local function smartDig(direction)
|
||||
direction = direction or "forward"
|
||||
|
||||
local digFunc, inspectFunc
|
||||
if direction == "forward" then
|
||||
digFunc = turtle.dig
|
||||
inspectFunc = turtle.inspect
|
||||
elseif direction == "up" then
|
||||
digFunc = turtle.digUp
|
||||
inspectFunc = turtle.inspectUp
|
||||
elseif direction == "down" then
|
||||
digFunc = turtle.digDown
|
||||
inspectFunc = turtle.inspectDown
|
||||
end
|
||||
|
||||
local hasBlock, data = inspectFunc()
|
||||
if hasBlock then
|
||||
if isUnbreakable(data.name) then
|
||||
return false, false, data.name
|
||||
end
|
||||
local valuable = isValuableBlock(data.name)
|
||||
digFunc()
|
||||
return true, valuable, data.name
|
||||
end
|
||||
return false, false, nil
|
||||
end
|
||||
|
||||
-- Pathfinding (improved with obstacle handling)
|
||||
local function getDistance(pos1, pos2)
|
||||
return math.abs(pos1.x - pos2.x) + math.abs(pos1.y - pos2.y) + math.abs(pos1.z - pos2.z)
|
||||
end
|
||||
|
||||
-- Try to dig and move forward
|
||||
local function forceForward()
|
||||
for i = 1, 5 do
|
||||
if smartForward() then
|
||||
return true
|
||||
end
|
||||
smartDig("forward")
|
||||
sleep(0.3)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Try to dig and move up
|
||||
local function forceUp()
|
||||
for i = 1, 5 do
|
||||
if smartUp() then
|
||||
return true
|
||||
end
|
||||
smartDig("up")
|
||||
sleep(0.3)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Try to dig and move down
|
||||
local function forceDown()
|
||||
for i = 1, 5 do
|
||||
if smartDown() then
|
||||
return true
|
||||
end
|
||||
smartDig("down")
|
||||
sleep(0.3)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Advanced navigation with unstuck logic
|
||||
local function navigateTowards(target)
|
||||
if not state.position or not target then
|
||||
return false
|
||||
end
|
||||
|
||||
local dx = target.x - state.position.x
|
||||
local dy = target.y - state.position.y
|
||||
local dz = target.z - state.position.z
|
||||
|
||||
local lastPos = {x = state.position.x, y = state.position.y, z = state.position.z}
|
||||
|
||||
-- Prioritize vertical movement if needed
|
||||
if math.abs(dy) > 3 then
|
||||
if dy > 0 then
|
||||
if forceUp() then
|
||||
state.stuckCounter = 0
|
||||
return false
|
||||
end
|
||||
else
|
||||
if forceDown() then
|
||||
state.stuckCounter = 0
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Horizontal movement
|
||||
local targetFacing
|
||||
if math.abs(dx) > math.abs(dz) then
|
||||
targetFacing = dx > 0 and 1 or 3
|
||||
else
|
||||
targetFacing = dz > 0 and 2 or 0
|
||||
end
|
||||
|
||||
-- Face the right direction
|
||||
while facing ~= targetFacing do
|
||||
smartTurnRight()
|
||||
end
|
||||
|
||||
-- Try to move forward
|
||||
if forceForward() then
|
||||
state.stuckCounter = 0
|
||||
else
|
||||
-- Stuck! Try alternative routes
|
||||
state.stuckCounter = state.stuckCounter + 1
|
||||
print("Stuck counter: " .. state.stuckCounter)
|
||||
|
||||
if state.stuckCounter > config.maxStuckAttempts then
|
||||
print("Trying alternative path...")
|
||||
state.stuckCounter = 0
|
||||
|
||||
-- Try going up to go over obstacle
|
||||
if forceUp() then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Try going around
|
||||
smartTurnRight()
|
||||
if forceForward() then
|
||||
return false
|
||||
end
|
||||
|
||||
smartTurnLeft()
|
||||
smartTurnLeft()
|
||||
if forceForward() then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Last resort: dig down and try lower path
|
||||
smartTurnRight()
|
||||
forceDown()
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if we're close enough
|
||||
return getDistance(state.position, target) < 2
|
||||
end
|
||||
|
||||
-- Status broadcasting
|
||||
function broadcastStatus()
|
||||
updateFuel()
|
||||
updateInventory()
|
||||
updatePosition()
|
||||
|
||||
modem.transmit(STATUS_CHANNEL, CHANNEL_RECEIVE, {
|
||||
type = "status",
|
||||
turtleID = os.getComputerID(),
|
||||
mode = state.mode,
|
||||
position = state.position,
|
||||
homePosition = state.homePosition,
|
||||
fuel = state.fuel,
|
||||
inventoryCount = #state.inventory,
|
||||
inventory = state.inventory,
|
||||
facing = facing
|
||||
})
|
||||
end
|
||||
|
||||
-- Return to home with better navigation
|
||||
local function returnHome()
|
||||
print("Returning home...")
|
||||
state.mode = "returning"
|
||||
state.stuckCounter = 0
|
||||
broadcastStatus()
|
||||
|
||||
local maxAttempts = 1000
|
||||
local attempts = 0
|
||||
|
||||
while state.homePosition and state.position and
|
||||
getDistance(state.position, state.homePosition) > 1 and
|
||||
attempts < maxAttempts do
|
||||
|
||||
-- Check for stop command
|
||||
if state.mode ~= "returning" then
|
||||
print("Return cancelled")
|
||||
return
|
||||
end
|
||||
|
||||
updateFuel()
|
||||
if needsRefuel() then
|
||||
print("Low fuel, trying to refuel...")
|
||||
if tryRefuel() then
|
||||
print("Refueled!")
|
||||
else
|
||||
print("WARNING: Out of fuel!")
|
||||
state.mode = "idle"
|
||||
broadcastStatus()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local arrived = navigateTowards(state.homePosition)
|
||||
if arrived then
|
||||
break
|
||||
end
|
||||
|
||||
attempts = attempts + 1
|
||||
|
||||
-- Update GPS position every few steps
|
||||
if attempts % 10 == 0 then
|
||||
updatePosition()
|
||||
print("Distance to home: " .. getDistance(state.position, state.homePosition))
|
||||
end
|
||||
|
||||
sleep(0.1)
|
||||
end
|
||||
|
||||
if attempts >= maxAttempts then
|
||||
print("Could not reach home - gave up after " .. maxAttempts .. " attempts")
|
||||
else
|
||||
print("Arrived at home!")
|
||||
end
|
||||
|
||||
state.mode = "idle"
|
||||
state.stuckCounter = 0
|
||||
broadcastStatus()
|
||||
end
|
||||
|
||||
-- Exploration algorithm
|
||||
local function exploreStep()
|
||||
-- Check all directions for valuable ores
|
||||
for _, direction in ipairs({"forward", "up", "down"}) do
|
||||
local dug, valuable, blockName = smartDig(direction)
|
||||
if valuable then
|
||||
print("Found: " .. blockName)
|
||||
broadcastStatus()
|
||||
end
|
||||
end
|
||||
|
||||
-- Random exploration with preference for going deeper
|
||||
local r = math.random(1, 10)
|
||||
if r <= 3 then
|
||||
-- Go down 30% of the time
|
||||
if not smartDown() then
|
||||
smartDig("down")
|
||||
smartDown()
|
||||
end
|
||||
elseif r <= 5 then
|
||||
-- Turn
|
||||
if math.random() > 0.5 then
|
||||
smartTurnRight()
|
||||
else
|
||||
smartTurnLeft()
|
||||
end
|
||||
else
|
||||
-- Move forward
|
||||
if not smartForward() then
|
||||
smartDig("forward")
|
||||
if not smartForward() then
|
||||
smartTurnRight()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Command handling
|
||||
local commands = {
|
||||
forward = function() return smartForward(), "Moved forward" end,
|
||||
back = function() return smartBack(), "Moved back" end,
|
||||
up = function() return smartUp(), "Moved up" end,
|
||||
down = function() return smartDown(), "Moved down" end,
|
||||
turnLeft = function() return smartTurnLeft(), "Turned left" end,
|
||||
turnRight = function() return smartTurnRight(), "Turned right" end,
|
||||
dig = function()
|
||||
local dug, val, name = smartDig("forward")
|
||||
return dug, dug and "Dug: " .. (name or "block") or "Nothing to dig"
|
||||
end,
|
||||
digUp = function()
|
||||
local dug, val, name = smartDig("up")
|
||||
return dug, dug and "Dug up: " .. (name or "block") or "Nothing above"
|
||||
end,
|
||||
digDown = function()
|
||||
local dug, val, name = smartDig("down")
|
||||
return dug, dug and "Dug down: " .. (name or "block") or "Nothing below"
|
||||
end,
|
||||
place = function() return turtle.place(), "Placed" end,
|
||||
select = function(slot) return turtle.select(slot), "Selected slot " .. slot end,
|
||||
refuel = function()
|
||||
local success = tryRefuel()
|
||||
updateFuel()
|
||||
broadcastStatus()
|
||||
return success, success and ("Refueled! Now: " .. state.fuel) or "No fuel"
|
||||
end,
|
||||
status = function() broadcastStatus() return true, "Status sent" end,
|
||||
|
||||
-- Autonomous commands
|
||||
setHome = function() return setHome(), "Home set" end,
|
||||
|
||||
explore = function()
|
||||
print("Explore command received")
|
||||
state.mode = "exploring"
|
||||
state.stuckCounter = 0
|
||||
broadcastStatus()
|
||||
return true, "Starting exploration"
|
||||
end,
|
||||
|
||||
returnHome = function()
|
||||
print("Return home command received")
|
||||
state.mode = "returning"
|
||||
state.stuckCounter = 0
|
||||
broadcastStatus()
|
||||
return true, "Returning home"
|
||||
end,
|
||||
|
||||
stop = function()
|
||||
print("STOP command received")
|
||||
state.mode = "idle"
|
||||
state.stuckCounter = 0
|
||||
broadcastStatus()
|
||||
return true, "Stopped"
|
||||
end,
|
||||
|
||||
manual = function()
|
||||
state.mode = "manual"
|
||||
broadcastStatus()
|
||||
return true, "Manual control"
|
||||
end,
|
||||
}
|
||||
|
||||
-- Process incoming messages
|
||||
local function processMessage(message)
|
||||
if type(message) == "table" and message.command then
|
||||
print("Command: " .. message.command)
|
||||
|
||||
local handler = commands[message.command]
|
||||
if handler then
|
||||
local success, result = handler(message.param)
|
||||
|
||||
modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, {
|
||||
status = success and "ok" or "error",
|
||||
message = result or "",
|
||||
turtleID = os.getComputerID()
|
||||
})
|
||||
|
||||
broadcastStatus()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Main loop
|
||||
print("Initializing...")
|
||||
updatePosition()
|
||||
updateFuel()
|
||||
|
||||
if not state.position then
|
||||
print("WARNING: No GPS signal!")
|
||||
print("Limited functionality available")
|
||||
end
|
||||
|
||||
print("Ready! Waiting for commands...")
|
||||
broadcastStatus()
|
||||
|
||||
-- Main execution loop
|
||||
parallel.waitForAny(
|
||||
function()
|
||||
-- Status broadcast loop
|
||||
while true do
|
||||
sleep(config.statusUpdateInterval)
|
||||
broadcastStatus()
|
||||
end
|
||||
end,
|
||||
|
||||
function()
|
||||
-- Command processing loop
|
||||
while true do
|
||||
local event, side, channel, replyChannel, message = os.pullEvent()
|
||||
|
||||
if event == "modem_message" then
|
||||
processMessage(message)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
function()
|
||||
-- Autonomous execution loop
|
||||
while true do
|
||||
if state.mode == "exploring" then
|
||||
updateFuel()
|
||||
|
||||
-- Check if we should stop
|
||||
if needsRefuel() or inventoryFull() then
|
||||
print("Need to return home")
|
||||
state.mode = "returning"
|
||||
broadcastStatus()
|
||||
else
|
||||
exploreStep()
|
||||
sleep(0.2)
|
||||
end
|
||||
|
||||
elseif state.mode == "returning" then
|
||||
returnHome()
|
||||
|
||||
else
|
||||
-- Idle or manual mode
|
||||
sleep(0.5)
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
Reference in New Issue
Block a user