Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- logFile=fs.open("/usr/apis/turtle2/turtle2.log","a")
- if logFile then
- oldPrint=print
- oldError=error
- print = function(...)
- oldPrint(...)
- logFile.writeLine(...)
- end
- error = function(...)
- logFile.writeLine(...)
- oldError(...)
- end
- else
- print("Warning: couldn't open log file")
- end
- if not turtle then
- error( "Cannot load turtle API on computer" )
- end
- native = turtle.native or turtle
- local function waitForResponse( _id )
- local event, responseID, success
- while event ~= "turtle_response" or responseID ~= _id do
- event, responseID, success = os.pullEvent( "turtle_response" )
- end
- return success
- end
- local function wrap( _sCommand )
- return function(...)
- local id = native[_sCommand]( ... )
- if id == -1 then
- return false
- end
- return waitForResponse ( id )
- end
- end
- -- Wrap standard commands
- local turtle, turtle2 = {}, {}
- turtle["getItemCount"], turtle2["getItemCount"] = native.getItemCount, native.getItemCount
- turtle["getItemSpace"], turtle2["getItemSpace"] = native.getItemSpace, native.getItemSpace
- turtle["getFuelLevel"], turtle2["getFuelLevel"] = native.getFuelLevel, native.getFuelLevel
- for k,v in pairs( native ) do
- if type( k ) == "string" and type( v ) == "function" then
- if turtle[k] == nil then
- turtle[k], turtle2[k] = wrap( k ), wrap ( k )
- end
- end
- end
- -- Wrap peripheral commands
- if peripheral.getType("left") == "workbench" then
- turtle["craft"]= function(...)
- local id = peripheral.call( "left", "craft", ...)
- return waitForResponse( id )
- end
- turtle2["craft"] = turtle["craft"]
- elseif peripheral.getType("right") == "workbench" then
- turtle["craft"] = function(...)
- local id = peripheral.call( "right", "craft", ...)
- return waitForResponse( id )
- end
- turtle2["craft"] = turtle["craft"]
- end
- -- Turtle Function overloading
- -- Random variable inits to default values
- --print("Initializing turtle...")
- turtle2.fuelSafety, turtle2.inventorySafety = true, true
- turtle2.fuelSafetyNet = 15
- turtle2.warned = false
- turtle2.returned = false
- turtle2.deltas = { [1] = vector.new(0,0,0) }
- turtle2.sumDeltas = { [1] = vector.new(0,0,0) }
- turtle2.distance = 0
- turtle2.currMoveDist = 0
- turtle2.heading = 0
- turtle2.blugdeon = false
- turtle2.turning = false
- -- for the following two options, a chest must be placed in slot 1
- -- and there must be a chest adjecent to the turtle at start of program
- -- Note: vertcially adjecent counts, but diagonally does not
- turtle2.autoRefuel = false -- will automatically try to refuel from slot 16
- -- if enabled, fuel must be first item in chest
- turtle2.greedyRefuel = false -- will attempt to refuel whenever possible
- -- and will try to drain chest of fuel
- turtle2.lastRunDistance = 0
- turtle2.autoDump = true
- turtle2.skipDump = { [1]=true, [16]=true }
- function turtle2:reloadConfigs(cPath)
- cPath = cPath or "/usr/apis/turtle2/turtle2.conf"
- if fs.exists(cPath) then
- h = fs.open(cPath,"r")
- while true do
- line = h.readLine()
- if not line then break end
- if line:match("warned") or line:match("deltas") or line:match("sumDeltas")
- or line:match("distance") or line:match("turning") then
- print("Warning: ", line, " is not a permitted configuration")
- else
- cString = "turtle2." .. line
- assert(loadstring(cString))()
- print("Config loaded: ", cString)
- end
- end
- end
- end
- function turtle2:saveConfigs(cPath)
- error("Function not yet implemented")
- end
- function turtle2:printDeltas()
- for k,v in pairs(self.deltas) do print(k,":",v) end
- end
- function turtle2:printSumDeltas()
- for k,v in pairs(self.sumDeltas) do print(k,":",v) end
- end
- -- Clear some old function just to be safe
- turtle2["forward"], turtle2["back"], turtle2["up"], turtle2["down"], turtle2["turnLeft"], turtle2["turnRight"] = nil, nil, nil, nil, nil, nil
- local function newMovement(newVector)
- turtle2.deltas[#turtle2.deltas+1] = newVector
- turtle2.distance = turtle2.distance + math.abs(turtle2.currMoveDist)
- end
- function turtle2:hasReturned()
- return self.returned
- end
- local function undoMoveVector(movement,self)
- --print("undoing vector <",movement,">")
- prevLength = 0
- tmpBlugdeon = false
- while movement:length() ~= 0 do
- if (not self.blugdeon) and (movement:length() == prevLength) then tmpBlugdeon,self.blugdeon = true, true
- elseif tmpBlugdeon and self.blugdeon then tmpBlugdeon, self.blugdeon = false, false end
- if movement.y > 0 then
- --print("going down")
- if self.blugdeon then turtle.digDown() end
- if turtle.down() then movement.y = movement.y - 1 end
- elseif movement.y < 0 then
- --print("going up")
- if self.blugdeon then turlte.digUp() end
- if turtle.up() then movement.y = movement.y + 1 end
- end
- --print(self.heading)
- if movement.x > 0 then
- --print("going -x")
- if self.heading == 0 then
- self:turnRight()
- self:turnRight()
- elseif self.heading == 1 then
- self:turnRight()
- elseif self.heading == 3 then
- self:turnLeft()
- end
- if self.blugdeon then turtle.dig() end
- if turtle.forward() then movement.x = movement.x - 1 end
- elseif movement.x < 0 then
- --print("going +x")
- if self.heading == 2 then
- self:turnRight()
- self:turnRight()
- elseif self.heading == 3 then
- self:turnRight()
- elseif self.heading == 1 then
- self:turnLeft()
- end
- if self.blugdeon then turtle.dig() end
- if turtle.forward() then movement.x = movement.x + 1 end
- end
- if movement.z < 0 then
- --print("going +z")
- if self.heading == 3 then
- self:turnRight()
- self:turnRight()
- elseif self.heading == 0 then
- self:turnRight()
- elseif self.heading == 2 then
- self:turnLeft()
- end
- if self.blugdeon then turtle.dig() end
- if turtle.forward() then movement.z = movement.z - 1 end
- elseif movement.z > 0 then
- --print("going -z")
- if self.heading == 1 then
- self:turnRight()
- self:turnRight()
- elseif self.heading == 2 then
- self:turnRight()
- elseif self.heading == 0 then
- self:turnLeft()
- end
- if self.blugdeon then turtle.dig() end
- if turtle.forward() then movement.z = movement.z + 1 end
- end
- end
- end
- local function addUpDeltas(force,self)
- --print("gothere1")
- if force or (#self.sumDeltas ~= #self.deltas) then self.sumDeltas = {} end
- --print("gothere2")
- self.sumDeltas[1] = self.deltas[1]
- --print(#self.deltas)
- for i=2,#self.deltas do
- --print(i)
- if self.sumDeltas[i] == nil then
- --print(self.sumDeltas[i-1])
- self.sumDeltas[i] = self.sumDeltas[i-1]:add(self.deltas[i])
- end
- end
- end
- local function optimizePath(self)
- print("Checking to see if I can optimize my path back home")
- addUpDeltas(false,self)
- local i,j
- for i = 1,#self.sumDeltas/2 do
- --print("i=",i)
- for j = #self.sumDeltas, i+1, -1 do
- --print("j=",j)
- --print(self.sumDeltas[i]:sub(self.sumDeltas[j]):length())
- if self.sumDeltas[i]:sub(self.sumDeltas[j]):length() == 0 then
- print("Found matching positions...")
- print("Shortening route home")
- for k = 1, (j-i) do
- --print("Removing deltas[",i+k,"]")
- --print(self.deltas[i+1])
- table.remove(self.deltas, i+1)
- end
- return true
- end
- end
- end
- return false
- end
- local findChest
- if peripheral.getType("right") == "idetect" then
- findChest = function()
- returnFunc = returnFunc or "dump"
- for i=0,2 do
- --vvv Chest id vvv
- if peripheral.call("right","IDetect") == 54 then return returnFunc:find("suck") and turtle2.suck or turlte2.dump end
- turtle2:turnRight()
- end
- -- check top and bottom
- if peripheral.call("right","IDetectUp") == 54 then return returnFunc:find("suck") and turtle2.suckUp or turtle2.dumpUp end
- if peripheral.call("right","IDetectDown") == 54 then return returnFunc:find("suck") and turtle2.suckDown or turtle2.dumpDown end
- -- Bummer. No chest :(
- return nil
- end
- else
- findChest = function()
- returnFunc = returnFunc or "dump"
- -- must assume chest is in slot 1
- turtle2.select(1)
- -- will search all sides then up and down
- for i=0,2 do
- if turtle.compare() then return returnFunc:find("suck") and turtle2.suck or turtle2.dump end
- turtle2:turnRight()
- end
- -- not any of the sides :( let's turn back the way we were
- turtle2:turnRight()
- -- check top and bottom
- if turtle2:compareUp() then return returnFunc:find("suck") and turtle2.suckUp or turtle2.dumpUp end
- if turtle2:compareDown() then return returnFunc:find("suck") and turtle2.suckDown or turtle2.dumpDown end
- -- Bummer. No chest :(
- return nil
- end
- end
- function turtle2:autoDumpFunc()
- if not self.autoDump then return false end
- dumpFunc = findChest("dump")
- if not dumpFunc then
- print("Could not find a chest next to me...")
- return false
- end
- print("Dumping all inventory...")
- for i = 1, 16 do
- if ((not turtle2.skipDump[i]) and (turtle2.getItemCount(i) ~=0 )) then
- --print("Dropping slot ",i)
- turtle2.select(i)
- dumpFunc()
- else
- --print("Skiping slot ",i)
- end
- end
- return true
- end
- function turtle2:autoRefuelFunc()
- if not self.autoRefuel then return false end
- suckFunc = findChest("suck")
- if not suckFunc then
- error("Could not find a chest next to me")
- end
- self.select(16)
- itemCount = self.getItemCount(16)
- while itemCount > 1 and self.refuel(itemCount-1) and self.greedyRefuel do
- suckFunc()
- itemCount = self.getItemCount(16)
- end
- return true
- end
- function turtle2:getPosition()
- addUpDeltas(true, self)
- return self.sumDeltas[#self.sumDeltas]
- end
- function turtle2:returnHome()
- print("Returning Home...")
- optimizePath(self)
- if self.blugdeon then
- undoMoveVector(self.sumDeltas[#self.sumDeltas],self)
- else
- for i = #self.deltas, 1, -1 do
- --sleep(1)
- undoMoveVector(self.deltas[i],self)
- end
- end
- self.deltas = {}
- self.lastRunDistance = self.distance
- self.distance = 0
- newMovement(vector.new(0,0,0))
- self.returned = true
- self:autoDumpFunc()
- self:autoRefuelFunc()
- return true
- end
- function turtle2:checkFuel()
- local reqFuel = self.distance + math.abs(self.currMoveDist) + self.fuelSafetyNet -- safety net
- --print(reqFuel)
- if turtle2.getFuelLevel() <= reqFuel then
- turtle2.select(16)
- if optimizePath(self) or turtle2.refuel() then self:checkFuel() end
- if self.warned == false then print("I appear to be low on Fuel...") end
- if self.fuelSafety then return self:returnHome()
- elseif self.warned == false then
- print("Warning!! Fuel Safety not engaged. Turtle will eventually run out of fuel");
- self.warned = true
- end
- end
- return false
- end
- function turtle2:checkInv()
- for slotNum = 1,16 do
- if turtle.getItemSpace(slotNum) > 0 then return false end
- end
- if self.warned == false then print("Inventory Full...") end
- if self.inventorySafety == true then return self:returnHome()
- elseif self.warned == false then
- print("Warning!! Inventory Safety not engaged. Turtle will eventually run out of fuel");
- self.warned = true
- end
- return false
- end
- local function horizMove(self,units)
- if self:checkFuel() or self:checkInv() then return end
- self.returned = false
- if units > 0 then move = turtle.forward
- elseif units < 0 then move = turtle.back
- else return true end
- if move() then
- --print(self.turning)
- --print(#self.deltas)
- --print(self.deltas[#self.deltas])
- if self.turning or self.deltas[#self.deltas].y ~= 0 then
- newMovement(vector.new(0,0,0))
- self.turning = false
- end
- self.currMoveDist = self.currMoveDist + units
- local tmpVector
- if self.heading == 0 then
- tmpVector = vector.new(units,0,0)
- elseif self.heading == 1 then
- tmpVector = vector.new(0,0,units)
- elseif self.heading == 2 then
- tmpVector = vector.new(-1*units, 0,0)
- elseif self.heading == 3 then
- tmpVector = vector.new(0,0,-1*units)
- end
- self.deltas[#self.deltas] = self.deltas[#self.deltas]:add(tmpVector)
- return true
- else
- return false
- end
- end
- function turtle2:forward(units)
- return horizMove(self,units or 1)
- end
- function turtle2:back(units)
- return horizMove(self,units and units*-1 or -1)
- end
- function turtle2:turnLeft()
- --read()
- if self.heading == 0 then
- self.heading = 3
- else
- self.heading = self.heading - 1
- end
- if turtle.turnLeft() then
- self.turning = true
- else
- return false
- end
- end
- function turtle2:turnRight()
- --read()
- if self.heading == 3 then
- self.heading = 0
- else
- self.heading = self.heading + 1
- end
- if turtle.turnRight() then
- self.turning = true
- return true
- else
- return false
- end
- end
- local function vertMove(self,units)
- --print(#self.deltas)
- --read()
- if self:checkFuel() or self:checkInv() then return end
- if units > 0 then move = turtle.up
- elseif units < 0 then move = turtle.down
- else return true end
- if move() then
- lastMove = self.deltas[#self.deltas]
- --[[print(lastMove)
- print(#self.deltas)
- print(self)
- print(self.deltas)
- print(self.deltas[#self.deltas])
- print(self.turning)]]
- if self.turning or (lastMove.y == 0 and (lastMove.x ~= 0 or lastMove.z ~= 0)) then
- newMovement(vector.new(0,units,0))
- else
- self.deltas[#self.deltas].y = self.deltas[#self.deltas].y + units
- end
- self.currMoveDist = self.currMoveDist + units
- turning = false
- return true
- else
- return false
- end
- end
- function turtle2:up(units)
- return vertMove(self,units or 1)
- end
- function turtle2:down(units)
- return vertMove(self,units and units*-1 or -1)
- end
- -- All commands defined
- -- One last thing to do because reasons
- newMovement(vector.new(0,0,0))
- if turtle2.autoRefuel then
- turtle2.select(16)
- if not (turtle2.getItemCount(16) ~= 0 and turtle2.refuel()) then
- print("Hey! Punk! You didn't put fuel in slot 16!")
- end
- end
- -- Put Commands into environment table
- local env = getfenv()
- for k,v in pairs( turtle2 ) do
- env[k] = v
- end
- --turtle2:reloadConfigs()
Advertisement
Add Comment
Please, Sign In to add comment