Dumfing

Miner

Dec 5th, 2020
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.69 KB | None | 0 0
  1. local robot = require("robot")
  2. local computer = require("computer")
  3. local serialization = require("serialization")
  4. local filesystem = require("filesystem")
  5. local component = require("component")
  6. local sides = require("sides")
  7.  
  8. local WORK_FILE = "/home/work.dat"
  9. local POS_FILE = "/home/pos.dat"
  10. local SECONDS_PER_BLOCK = 1.75
  11.  
  12.  
  13. local last_check_time = computer.uptime()
  14. local last_power_amount = computer.energy()
  15. local pos = {}
  16. local work = {}
  17. local average_rf_per_second, average_time_remaining
  18. local smoothing_strength = 0.75
  19. function load_state()
  20.   local resuming_work = false
  21.   if filesystem.exists(POS_FILE) then
  22.     local state_file = io.open(POS_FILE, "r")
  23.     pos = serialization.unserialize(state_file:read("*a"))
  24.     state_file:close()
  25.   else
  26.     pos = {x=0, y=0, z=0, rot=0, docking=false}
  27.     save_pos()
  28.   end
  29.  
  30.   if filesystem.exists(WORK_FILE) then
  31.     local work_file = io.open(WORK_FILE, "r")
  32.     work = serialization.unserialize(work_file:read("*a"))
  33.     work_file:close()
  34.     resuming_work = true
  35.   else
  36.     work = {}
  37.     save_work()
  38.   end
  39.   return resuming_work
  40. end
  41.  
  42. function power_percentage()
  43.     return computer.energy() / computer.maxEnergy()
  44. end
  45.  
  46. function check_power_usage()
  47.   local current_power = computer.energy()
  48.   local current_check_time = computer.uptime()
  49.  
  50.   local power_change = current_power - last_power_amount
  51.   local time_change = current_check_time - last_check_time
  52.   if time_change == 0 then
  53.     time_change = 1
  54.   end
  55.   local rf_per_second = power_change/time_change
  56.  
  57.   last_check_time = current_check_time
  58.   last_power_amount = current_power
  59.   if average_rf_per_second == nil then
  60.     average_rf_per_second = rf_per_second
  61.   else
  62.     average_rf_per_second = average_rf_per_second * smoothing_strength + rf_per_second * (1-smoothing_strength)
  63.   end
  64.  
  65.   local time_left = math.max(1/-average_rf_per_second * computer.energy(), 0)
  66.   if rf_per_second > 0 then
  67.     return average_rf_per_second, 1e309
  68.   end
  69.  
  70.   if average_time_left == nil then
  71.     average_time_left = time_left
  72.   else
  73.     average_time_left = average_time_left * smoothing_strength + time_left * (1 - smoothing_strength)
  74.   end
  75.  
  76.   return average_rf_per_second, average_time_left
  77. end
  78.  
  79. function save_pos()
  80.   local state_file = io.open(POS_FILE,"w")
  81.   state_file:write(serialization.serialize(pos))
  82.   state_file:flush()
  83.   state_file:close()
  84. end
  85.  
  86. function save_work()
  87.   local work_file = io.open(WORK_FILE, "w")
  88.   work_file:write(serialization.serialize(work, 1e309))
  89.   work_file:flush()
  90.   work_file:close()
  91. end
  92.  
  93. function move_forward()
  94.   local detection, type = robot.detect()
  95.   while detection and not (should_return() and not pos["docking"]) do
  96.     robot.swing()
  97.     robot.suck()
  98.     detection, type = robot.detect()
  99.   end
  100.   if robot.forward() then
  101.     local inc_axis = nil
  102.     local dec_axis = nil
  103.     if pos["rot"] == 0 then
  104.       inc_axis = "x"
  105.       dec_axis = nil
  106.     elseif pos["rot"] == 1 then
  107.       inc_axis = "z"
  108.       dec_axis = nil
  109.     elseif pos["rot"] == 2 then
  110.       inc_axis = nil
  111.       dec_axis = "x"
  112.     elseif pos["rot"] == 3 then
  113.       inc_axis = nil
  114.       dec_axis = "z"
  115.     else
  116.       error("Invalid rotation value")
  117.     end
  118.     if inc_axis ~= nil then
  119.       pos[inc_axis] = pos[inc_axis] + 1
  120.     elseif dec_axis ~= nil then
  121.       pos[dec_axis] = pos[dec_axis] - 1
  122.     else
  123.       error("Invalid inc/dec axis")
  124.     end
  125.   end
  126.   save_pos()
  127. end
  128.  
  129. function turn_left()
  130.   robot.turnLeft()
  131.   pos["rot"] = (pos["rot"] + 3) % 4
  132.   save_pos()
  133. end
  134.  
  135. function turn_right()
  136.   robot.turnRight()
  137.   pos["rot"] = (pos["rot"] + 1) % 4
  138.   save_pos()
  139. end
  140.  
  141. function face_direction(direction)
  142.   local direction_delta = (pos["rot"] - direction + 4) % 4
  143.  
  144.   if direction_delta == 1 then
  145.     turn_left()
  146.   elseif direction_delta == 3 then
  147.     turn_right()
  148.   elseif direction_delta == 2 then
  149.     turn_right()
  150.     turn_right()
  151.   end
  152. end
  153.  
  154. function move_up()
  155.   local detection, type = robot.detectUp()
  156.  
  157.   while detection and not (should_return() and not pos["docking"]) do
  158.     robot.swingUp()
  159.     robot.suckUp()
  160.     detection, type = robot.detectUp()
  161.   end
  162.  
  163.   if robot.up() then
  164.     pos["y"] = pos["y"] + 1
  165.   end
  166.   save_pos()
  167. end
  168.  
  169. function move_down()
  170.   local detection, type = robot.detectDown()
  171.  
  172.   while detection and not (should_return() and not pos["docking"]) do
  173.     robot.swingDown()
  174.     robot.suckDown()
  175.     detection, type = robot.detectDown()
  176.   end
  177.  
  178.   if robot.down() then
  179.     pos["y"] = pos["y"] - 1
  180.   end
  181.   save_pos()
  182. end
  183.  
  184. function move_relative(x, y, z)
  185.   if x < 0 then
  186.     face_direction(2)
  187.   elseif x > 0 then
  188.     face_direction(0)
  189.   end
  190.  
  191.   while x ~= 0 and not (should_return() and not pos["docking"])do
  192.     move_forward()
  193.     x = x - (x/math.abs(x))
  194.   end
  195.  
  196.   if z < 0 then
  197.     face_direction(3)
  198.   elseif z > 0 then
  199.     face_direction(1)
  200.   end
  201.    
  202.   while z ~= 0 and not (should_return() and not pos["docking"])do
  203.     move_forward()
  204.     z = z - (z/math.abs(z))
  205.   end
  206.  
  207.   while y ~= 0 and not (should_return() and not pos["docking"])do
  208.     if y < 0 then
  209.       move_down()
  210.     elseif y > 0 then
  211.       move_up()
  212.     end
  213.  
  214.     y = y - (y/math.abs(y))
  215.   end
  216. end
  217.  
  218. function dock()
  219.   pos["docking"] = true
  220.   move_to(0, 0, 0)
  221.   face_direction(1)
  222.   deposit_items()
  223.   face_direction(0)
  224.   while power_percentage() < 0.99 do
  225.     os.sleep(1)
  226.     io.write(".")
  227.   end
  228.   print("")
  229.   pos["docking"] = false
  230. end
  231.  
  232. function deposit_items()
  233.   if pos["x"] == 0 and pos["y"] == 0 and pos["z"] == 0 then
  234.     local other_index = 1
  235.     for i = 1, robot.inventorySize() do
  236.       robot.select(i)
  237.       if component.inventory_controller.getStackInInternalSlot(i) ~= nil then
  238.         while component.inventory_controller.getStackInSlot(sides.front, other_index) ~= nil do
  239.           other_index = other_index + 1
  240.         end
  241.         component.inventory_controller.dropIntoSlot(sides.front, other_index)
  242.       end
  243.     end
  244.   end
  245. end    
  246.  
  247. function dist_from_dock()
  248.   return math.abs(pos["x"]) + math.abs(pos["y"]) + math.abs(pos["z"])
  249. end
  250.  
  251. function should_return()
  252.   local power_usage, time_remaining = check_power_usage()
  253.   local time_to_return = dist_from_dock() * SECONDS_PER_BLOCK
  254.   print(string.format("PU: %8.4f ATR: %8.2f TTR: %6.2f", power_usage, time_remaining, time_to_return))
  255.   if time_remaining < time_to_return + 20 then
  256.     print("Low power")
  257.     return true
  258.   end
  259.  
  260.   local open_spaces = 0
  261.  
  262.   for i = 1, robot.inventorySize() do
  263.     if robot.count(i) == 0 then
  264.       open_spaces = open_spaces + 1
  265.     end
  266.   end
  267.  
  268.   if open_spaces == 0 then
  269.     return true
  270.   end
  271.    
  272.   return false  
  273. end
  274.  
  275. function push_work(obj)
  276.   table.insert(work, obj)
  277.   save_work()
  278. end
  279.  
  280. function pop_work()
  281.   local val = table.remove(work, #work)
  282.   save_work()
  283.   return val
  284. end
  285.  
  286. function peek_work()
  287.   return work[#work]
  288. end
  289.  
  290. function move_to(x, y, z)
  291.   local dX = x - pos["x"]
  292.   local dY = y - pos["y"]
  293.   local dZ = z - pos["z"]
  294.   move_relative(dX, dY, dZ)
  295. end
  296.  
  297. function rectangle(x, y, z, x2, z2)
  298.   local dX = x2 - x
  299.   local dZ = z2 - z
  300.  
  301.   local sX, sZ, eX, eZ
  302.  
  303.   if dX < 0 then
  304.     sX = x2
  305.     eX = x
  306.   else
  307.     sX = x
  308.     eX = x2
  309.   end
  310.  
  311.   if dZ < 0 then
  312.     sZ = z2
  313.     eZ = z
  314.   else
  315.     sZ = z
  316.     eZ = z2
  317.   end
  318.   assert(sX < eX)
  319.   assert(sZ < eZ)
  320.   local on_left = true
  321.   for iX = sX, eX do
  322.     if on_left then
  323.       for iZ = sZ, eZ do
  324.         push_work({["x"] = iX, ["y"] = y, ["z"] = iZ, ["type"] = 0 })
  325.       end
  326.     else
  327.       for iZ = sZ, eZ do
  328.         push_work({["x"] = iX, ["y"] = y, ["z"] = sZ + eZ - iZ, ["type"] = 0})
  329.       end
  330.     end
  331.     on_left = not on_left
  332.   end
  333. end
  334.  
  335. function quarry(x, y, z, x2, y2, z2)
  336.  
  337.   local dY = y2 - y
  338.  
  339.   local sY, eY
  340.   if dY > 0 then
  341.     sY = y
  342.     eY = y2
  343.   else
  344.     sY = y2
  345.     eY = y
  346.   end
  347.   if math.abs(dY) > 0 then
  348.     push_work({["x"]=x, ["y"] = eY-1, ["z"]=z, ["x2"]=x2, ["y2"]=sY, ["z2"]=z2, ["type"]="quarry"})
  349.   end
  350.   push_work({["x"]=x, ["y"]=eY, ["z"]=z, ["x2"]=x2, ["z2"]=z2, ["type"]="rect"})
  351. end
  352.  
  353. function execute_work()
  354.   local next_step = peek_work()
  355.   if should_return() then
  356.     print("docking")
  357.     dock()
  358.   elseif next_step["type"] == 0 then
  359.     move_to(next_step["x"], next_step["y"], next_step["z"])
  360.     pop_work()
  361.   elseif next_step["type"] == "rect" then
  362.     pop_work()
  363.     rectangle(next_step["x"], next_step["y"], next_step["z"], next_step["x2"], next_step["z2"])
  364.   elseif next_step["type"] == "quarry" then
  365.     pop_work()
  366.     quarry(next_step["x"], next_step["y"], next_step["z"], next_step["x2"], next_step["y2"], next_step["z2"])
  367.   else
  368.     error("Invalid work")
  369.   end
  370. end
  371.  
  372. if not load_state() then
  373.   dock()
  374.   quarry(27, -36, -10, 31, -66, 10)
  375. end
  376. while #work > 0 do
  377.   execute_work()  
  378. end
  379. dock()
Add Comment
Please, Sign In to add comment