Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Movescript - A simplified robot script for ComputerCraft.
- Author: Andrew Lalis <andrewlalisofficial@gmail.com>
- Movescript provides a simpler, conciser way to program "turtles" (robots), so
- that you don't need to get tired of typing "turtle.forward()" over and over.
- ]]--
- local t = turtle
- -- The movescript module. Functions defined within this table are exported.
- local movescript = {}
- local function debug(msg, settings)
- if settings and settings.debug then
- print("[MS] " .. msg)
- end
- end
- -- Helper function for turtle to dig backwards.
- function t.digBack(side)
- t.turnRight()
- t.turnRight()
- t.dig(side)
- t.turnRight()
- t.turnRight()
- end
- -- Helper function for turtle to detect backwards.
- function t.detectBack()
- t.turnRight()
- t.turnRight()
- local result = t.detect()
- t.turnRight()
- t.turnRight()
- return result
- end
- -- The default settings to apply to any robot movement, if none are specified.
- local defaultMovementSettings = {
- safe = true,
- destructive = false,
- fuels = {"minecraft:coal", "minecraft:charcoal"}
- }
- local function goDirection(dirFunction, digFunction, detectFunction, settings)
- settings = settings or defaultMovementSettings
- safe = settings.safe or defaultMovementSettings.safe
- destructive = settings.destructive or defaultMovementSettings.destructive
- local success = dirFunction()
- if not safe then return end
- while not success do
- debug("Unable to move.", settings)
- if destructive and detectFunction() then
- debug("Detected a block in the way; attempting to remove it.", settings)
- digFunction()
- end
- success = dirFunction()
- end
- end
- local function goUp(settings)
- debug("Moving up.", settings)
- goDirection(t.up, t.digUp, t.detectUp, settings)
- end
- local function goDown(settings)
- debug("Moving down.", settings)
- goDirection(t.down, t.digDown, t.detectDown, settings)
- end
- local function goForward(settings)
- debug("Moving forward.", settings)
- goDirection(t.forward, t.dig, t.detect, settings)
- end
- local function goBack(settings)
- debug("Moving back.", settings)
- goDirection(t.back, t.digBack, t.detectBack, settings)
- end
- local function goRight(settings)
- debug("Turning right.", settings)
- t.turnRight()
- end
- local function goLeft(settings)
- debug("Turning left.", settings)
- t.turnLeft()
- end
- local actionMap = {
- ["U"] = {f = goUp, needsFuel = true},
- ["D"] = {f = goDown, needsFuel = true},
- ["L"] = {f = goLeft, needsFuel = false},
- ["R"] = {f = goRight, needsFuel = false},
- ["F"] = {f = goForward, needsFuel = true},
- ["B"] = {f = goBack, needsFuel = true},
- ["P"] = {f = t.place, needsFuel = false},
- ["Pu"] = {f = t.placeUp, needsFuel = false},
- ["Pd"] = {f = t.placeDown, needsFuel = false},
- ["A"] = {f = t.attack, needsFuel = false},
- ["Au"] = {f = t.attackUp, needsFuel = false},
- ["Ad"] = {f = t.attackDown, needsFuel = false}
- }
- -- Tries to refuel the turtle from all slots that contain a valid fuel.
- -- Returns a boolean indicating if at least one piece of fuel was consumed.
- local function refuelAll(settings)
- debug("Refueling...", settings)
- local fuels = settings.fuels or defaultMovementSettings.fuels
- local refueled = false
- for slot = 1, 16 do
- local item = t.getItemDetail(slot)
- for _, fuelName in pairs(fuels) do
- if item.name == fuelName then
- t.select(i)
- if t.refuel(item.count) then refueled = true end
- break
- end
- end
- end
- return refueled
- end
- -- Blocks until the turtle's fuel level is at least at the required level.
- local function refuelToAtLeast(requiredLevel, settings)
- refuelAll(settings)
- while t.getFuelLevel < requiredLevel do
- print(
- "[MS] Fuel level is too low. Level: " .. t.getFuelLevel() .. ". Required: " .. requiredLevel ..
- ". Please add some of the following fuels:"
- )
- local fuels = settings.fuels or defaultMovementSettings.fuels
- for _, fuelName in pairs(fuels) do
- print(" - " .. fuelName)
- end
- local fuelUpdated = false
- while not fuelUpdated do
- os.pullEvent("turtle_inventory")
- fuelUpdated = refuelAll()
- end
- end
- end
- -- Executes a single instruction. An instruction is a table with an "action"
- -- and some attributes, such as if it needs fuel or not.
- local function executeInstruction(instruction, settings)
- local action = actionMap[instruction.action]
- if action then
- debug("Executing action \"" .. instruction.action .. "\" " .. instruction.count .. " times.", settings)
- if action.needsFuel and instruction.count > t.getFuelLevel() then
- local fuelRequired = instruction.count
- refuelToAtLeast(fuelRequired, settings)
- end
- for i = 1, instruction.count do action.f() end
- end
- end
- local function parseScript(script, settings)
- local instructions = {}
- for instruction in string.gfind(script, "%W*(%d*%u%l*)%W*") do
- local countIdx, countIdxEnd = string.find(instruction, "%d+")
- local actionIdx, actionIdxEnd = string.find(instruction, "%u%l*")
- local count = 1
- if countIdx ~= nil then
- count = tonumber(string.sub(instruction, countIdx, countIdxEnd))
- end
- local action = string.sub(instruction, actionIdx, actionIdxEnd)
- if count < 1 or count > t.getFuelLimit() then
- error("Instruction at index " .. actionIdx .. " has an invalid count of " .. count .. ". It should be >= 1 and <= " .. t.getFuelLimit())
- end
- if actionMap[action] == nil then
- error("Instruction at index " .. actionIdx .. ", \"" .. action .. "\", does not refer to a valid action.")
- end
- table.insert(instructions, {action = action, count = count})
- debug("Parsed instruction: " .. instruction, settings)
- end
- return instructions
- end
- function movescript.run(script, settings)
- settings = settings or defaultMovementSettings
- script = script or ""
- debug("Executing script: " .. script, settings)
- local instructions = parseScript(script, settings)
- for _, instruction in pairs(instructions) do
- executeInstruction(instruction)
- end
- end
- return movescript
Add Comment
Please, Sign In to add comment