HandieAndy

Movescript 2

Dec 17th, 2022 (edited)
644
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.43 KB | Gaming | 0 0
  1. --[[
  2. Movescript - A simplified robot script for ComputerCraft.
  3.  
  4. Author: Andrew Lalis <andrewlalisofficial@gmail.com>
  5.  
  6. Movescript provides a simpler, conciser way to program "turtles" (robots), so
  7. that you don't need to get tired of typing "turtle.forward()" over and over.
  8.  
  9. ]]--
  10. local t = turtle
  11.  
  12. -- The movescript module. Functions defined within this table are exported.
  13. local movescript = {}
  14.  
  15. local function debug(msg, settings)
  16.     if settings and settings.debug then
  17.         print("[MS] " .. msg)
  18.     end
  19. end
  20.  
  21. -- Helper function for turtle to dig backwards.
  22. function t.digBack(side)
  23.     t.turnRight()
  24.     t.turnRight()
  25.     t.dig(side)
  26.     t.turnRight()
  27.     t.turnRight()
  28. end
  29.  
  30. -- Helper function for turtle to detect backwards.
  31. function t.detectBack()
  32.     t.turnRight()
  33.     t.turnRight()
  34.     local result = t.detect()
  35.     t.turnRight()
  36.     t.turnRight()
  37.     return result
  38. end
  39.  
  40. -- The default settings to apply to any robot movement, if none are specified.
  41. local defaultMovementSettings = {
  42.     safe = true,
  43.     destructive = false,
  44.     fuels = {"minecraft:coal", "minecraft:charcoal"}
  45. }
  46.  
  47. local function goDirection(dirFunction, digFunction, detectFunction, settings)
  48.     settings = settings or defaultMovementSettings
  49.     safe = settings.safe or defaultMovementSettings.safe
  50.     destructive = settings.destructive or defaultMovementSettings.destructive
  51.     local success = dirFunction()
  52.     if not safe then return end
  53.     while not success do
  54.         debug("Unable to move.", settings)
  55.         if destructive and detectFunction() then
  56.             debug("Detected a block in the way; attempting to remove it.", settings)
  57.             digFunction()
  58.         end
  59.         success = dirFunction()
  60.     end
  61. end
  62.  
  63. local function goUp(settings)
  64.     debug("Moving up.", settings)
  65.     goDirection(t.up, t.digUp, t.detectUp, settings)
  66. end
  67.  
  68. local function goDown(settings)
  69.     debug("Moving down.", settings)
  70.     goDirection(t.down, t.digDown, t.detectDown, settings)
  71. end
  72.  
  73. local function goForward(settings)
  74.     debug("Moving forward.", settings)
  75.     goDirection(t.forward, t.dig, t.detect, settings)
  76. end
  77.  
  78. local function goBack(settings)
  79.     debug("Moving back.", settings)
  80.     goDirection(t.back, t.digBack, t.detectBack, settings)
  81. end
  82.  
  83. local function goRight(settings)
  84.     debug("Turning right.", settings)
  85.     t.turnRight()
  86. end
  87.  
  88. local function goLeft(settings)
  89.     debug("Turning left.", settings)
  90.     t.turnLeft()
  91. end
  92.  
  93. local actionMap = {
  94.     ["U"] = {f = goUp, needsFuel = true},
  95.     ["D"] = {f = goDown, needsFuel = true},
  96.     ["L"] = {f = goLeft, needsFuel = false},
  97.     ["R"] = {f = goRight, needsFuel = false},
  98.     ["F"] = {f = goForward, needsFuel = true},
  99.     ["B"] = {f = goBack, needsFuel = true},
  100.     ["P"] = {f = t.place, needsFuel = false},
  101.     ["Pu"] = {f = t.placeUp, needsFuel = false},
  102.     ["Pd"] = {f = t.placeDown, needsFuel = false},
  103.     ["A"] = {f = t.attack, needsFuel = false},
  104.     ["Au"] = {f = t.attackUp, needsFuel = false},
  105.     ["Ad"] = {f = t.attackDown, needsFuel = false}
  106. }
  107.  
  108. -- Tries to refuel the turtle from all slots that contain a valid fuel.
  109. -- Returns a boolean indicating if at least one piece of fuel was consumed.
  110. local function refuelAll(settings)
  111.     debug("Refueling...", settings)
  112.     local fuels = settings.fuels or defaultMovementSettings.fuels
  113.     local refueled = false
  114.     for slot = 1, 16 do
  115.         local item = t.getItemDetail(slot)
  116.         for _, fuelName in pairs(fuels) do
  117.             if item.name == fuelName then
  118.                 t.select(i)
  119.                 if t.refuel(item.count) then refueled = true end
  120.                 break
  121.             end
  122.         end
  123.     end
  124.     return refueled
  125. end
  126.  
  127. -- Blocks until the turtle's fuel level is at least at the required level.
  128. local function refuelToAtLeast(requiredLevel, settings)
  129.     refuelAll(settings)
  130.     while t.getFuelLevel < requiredLevel do
  131.         print(
  132.             "[MS] Fuel level is too low. Level: " .. t.getFuelLevel() .. ". Required: " .. requiredLevel ..
  133.             ". Please add some of the following fuels:"
  134.         )
  135.         local fuels = settings.fuels or defaultMovementSettings.fuels
  136.         for _, fuelName in pairs(fuels) do
  137.             print("  - " .. fuelName)
  138.         end
  139.         local fuelUpdated = false
  140.         while not fuelUpdated do
  141.             os.pullEvent("turtle_inventory")
  142.             fuelUpdated = refuelAll()
  143.         end
  144.     end
  145. end
  146.  
  147. -- Executes a single instruction. An instruction is a table with an "action"
  148. -- and some attributes, such as if it needs fuel or not.
  149. local function executeInstruction(instruction, settings)
  150.     local action = actionMap[instruction.action]
  151.     if action then
  152.         debug("Executing action \"" .. instruction.action .. "\" " .. instruction.count .. " times.", settings)
  153.         if action.needsFuel and instruction.count > t.getFuelLevel() then
  154.             local fuelRequired = instruction.count
  155.             refuelToAtLeast(fuelRequired, settings)
  156.         end
  157.         for i = 1, instruction.count do action.f() end
  158.     end
  159. end
  160.  
  161. local function parseScript(script, settings)
  162.     local instructions = {}
  163.     for instruction in string.gfind(script, "%W*(%d*%u%l*)%W*") do
  164.         local countIdx, countIdxEnd = string.find(instruction, "%d+")
  165.         local actionIdx, actionIdxEnd = string.find(instruction, "%u%l*")
  166.         local count = 1
  167.         if countIdx ~= nil then
  168.             count = tonumber(string.sub(instruction, countIdx, countIdxEnd))
  169.         end
  170.         local action = string.sub(instruction, actionIdx, actionIdxEnd)
  171.         if count < 1 or count > t.getFuelLimit() then
  172.             error("Instruction at index " .. actionIdx .. " has an invalid count of " .. count .. ". It should be >= 1 and <= " .. t.getFuelLimit())
  173.         end
  174.         if actionMap[action] == nil then
  175.             error("Instruction at index " .. actionIdx .. ", \"" .. action .. "\", does not refer to a valid action.")
  176.         end
  177.         table.insert(instructions, {action = action, count = count})
  178.         debug("Parsed instruction: " .. instruction, settings)
  179.     end
  180.     return instructions
  181. end
  182.  
  183. function movescript.run(script, settings)
  184.     settings = settings or defaultMovementSettings
  185.     script = script or ""
  186.     debug("Executing script: " .. script, settings)
  187.     local instructions = parseScript(script, settings)
  188.     for _, instruction in pairs(instructions) do
  189.         executeInstruction(instruction)
  190.     end
  191. end
  192.  
  193. return movescript
  194.  
Add Comment
Please, Sign In to add comment