Advertisement
bob558

Doob kopalka dubokop

Nov 3rd, 2020 (edited)
44
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- https://computercraft.ru/topic/2544-dubokop/
  2. --local component = require('component') -- подгрузить обертку из OpenOS
  3. --local computer = require('computer')
  4. local chunks = 9 -- количество чанков для добычи
  5. local min, max = 2.2, 40 -- минимальная и максимальная плотность
  6. local port = 1 -- порт для взаимодействия с роботом
  7. local X, Y, Z, D, border = 0, 0, 0, 0 -- переменные локальной системы координат
  8. local steps, turns = 0, 0 -- debug
  9. local WORLD = {x = {}, y = {}, z = {}} -- таблица меток
  10. local E_C, W_R = 0, 0 -- энергозатраты на один шаг и скорость износа
  11.  
  12. local function arr2a_arr(tbl) -- преобразование списка в ассоциативный массив
  13.   for i = #tbl, 1, -1 do
  14.    tbl[tbl[i]], tbl[i] = true, nil
  15.   end
  16. end
  17.  
  18. local quads = {{-7, -7}, {-7, 1}, {1, -7}, {1, 1}}
  19. local workbench = {1,2,3,5,6,7,9,10,11}
  20. local wlist = {'enderstorage:ender_storage'}
  21. local fragments = {'redstone','coal','dye','diamond','emerald'}
  22. local tails = {'cobblestone','granite','diorite','andesite','marble','limestone','dirt','gravel','sand','stained_hardened_clay','sandstone','stone','grass','end_stone','hardened_clay','mossy_cobblestone','planks','fence','torch','nether_brick','nether_brick_fence','nether_brick_stairs','netherrack','soul_sand'}
  23. arr2a_arr(wlist)
  24. arr2a_arr(fragments)
  25. arr2a_arr(tails)
  26.  
  27. local function add_component(name) -- получение прокси компонента
  28.   name = component.list(name)() -- получить адрес по имени
  29.   if name then -- если есть адрес
  30.     return component.proxy(name) -- вернуть прокси
  31.   end
  32. end
  33.  
  34. -- загрузка компонентов --
  35. local controller = add_component('inventory_controller')
  36. local chunkloader = add_component('chunkloader')
  37. local generator = add_component('generator')
  38. local crafting = add_component('crafting')
  39. local geolyzer = add_component('geolyzer')
  40. local tunnel = add_component('tunnel')
  41. local modem = add_component('modem')
  42. local robot = add_component('robot')
  43. local inventory = robot.inventorySize()
  44. local energy_level, sleep, report, remove_point, check, step, turn, smart_turn, go, scan, calibration, sorter, home, main, solar, ignore_check, inv_check
  45.  
  46. energy_level = function()
  47.   return computer.energy()/computer.maxEnergy()
  48. end
  49.  
  50. sleep = function(timeout)
  51.   local deadline = computer.uptime()+timeout
  52.   repeat
  53.     computer.pullSignal(deadline-computer.uptime())
  54.   until computer.uptime() >= deadline
  55. end
  56.  
  57. report = function(message, stop) -- рапорт о состоянии
  58.   message = '|'..X..' '..Y..' '..Z..'|\n'..message..'\nenergy level: '..math.floor(energy_level()*100)..'%' -- добавить к сообщению координаты и уровень энергии
  59.   if modem then -- если есть модем
  60.     modem.broadcast(port, message) -- послать сообщение через модем
  61.   elseif tunnel then -- если есть связанная карта
  62.     tunnel.send(message) -- послать сообщение через нее
  63.   end
  64.   computer.beep() -- пикнуть
  65.   if stop then -- если есть флаг завершения
  66.     if chunkloader then
  67.       chunkloader.setActive(false)
  68.     end
  69.     error(message,0) -- остановить работу программы
  70.   end
  71. end
  72.  
  73. remove_point = function(point) -- удаление меток
  74.   table.remove(WORLD.x, point) -- удалить метку из таблицы
  75.   table.remove(WORLD.y, point)
  76.   table.remove(WORLD.z, point)
  77. end
  78.  
  79. check = function(forcibly) -- проверка инструмента, батареи, удаление меток
  80.   if not ignore_check and (steps%32 == 0 or forcibly) then -- если пройдено 32 шага или включен принудительный режим
  81.     inv_check()
  82.     local delta = math.abs(X)+math.abs(Y)+math.abs(Z)+64 -- определить расстояние
  83.     if robot.durability()/W_R < delta then -- если инструмент изношен
  84.       report('tool is worn')
  85.       ignore_check = true
  86.       home(true) -- отправиться домой
  87.     end
  88.     if delta*E_C > computer.energy() then -- проверка уровня энергии
  89.       report('battery is low')
  90.       ignore_check = true
  91.       home(true) -- отправиться домой
  92.     end
  93.     if energy_level() < 0.3 then -- если энергии меньше 30%
  94.       local time = os.date('*t')
  95.       if generator and generator.count() == 0 and not forcibly then -- если есть генератор
  96.         report('refueling solid fuel generators')
  97.         for slot = 1, inventory do -- обойти инвентарь
  98.           robot.select(slot) -- выбрать слот
  99.           for gen in component.list('generator') do -- перебрать все генераторы
  100.             if component.proxy(gen).insert() then -- попробовать заправиться
  101.               break
  102.             end
  103.           end
  104.         end
  105.       elseif solar and geolyzer.isSunVisible() and -- проверить видимость солнца
  106.         (time.hour > 4 and time.hour < 17) then -- проверить время
  107.         while not geolyzer.canSeeSky() do -- пока не видно неба
  108.           step(1, true) -- сделать шаг вверх без проверки
  109.         end
  110.         report('recharging in the sun')
  111.         sorter(true)
  112.         while (energy_level() < 0.98) and geolyzer.isSunVisible() do
  113.           time = os.date('*t') -- время работы солнечной панели 05:30 - 18:30
  114.           if time.hour >= 5 and time.hour < 19 then
  115.             sleep(60)
  116.           else
  117.             break
  118.           end
  119.         end
  120.         report('return to work')
  121.       end
  122.     end
  123.   end
  124.   if #WORLD.x ~= 0 then -- если таблица меток не пуста
  125.     for i = 1, #WORLD.x do -- пройти по всем позициям
  126.       if WORLD.y[i] == Y and ((WORLD.x[i] == X and ((WORLD.z[i] == Z+1 and D == 0) or (WORLD.z[i] == Z-1 and D == 2))) or (WORLD.z[i] == Z and ((WORLD.x[i] == X+1 and D == 3) or (WORLD.x[i] == X-1 and D == 1)))) then
  127.         robot.swing(3)
  128.         remove_point(i)
  129.       end
  130.       if X == WORLD.x[i] and (Y-1 <= WORLD.y[i] and Y+1 >= WORLD.y[i]) and Z == WORLD.z[i] then
  131.         if WORLD.y[i] == Y+1 then -- добыть блок сверху, если есть
  132.           robot.swing(1)
  133.         elseif WORLD.y[i] == Y-1 then -- добыть блок снизу
  134.           robot.swing(0)
  135.         end
  136.         remove_point(i)
  137.       end
  138.     end
  139.   end
  140. end
  141.  
  142. step = function(side, ignore) -- функция движения на 1 блок
  143.   local result, obstacle = robot.swing(side)
  144.   if not result and obstacle ~= 'air' and robot.detect(side) then -- если блок нельзя разрушить
  145.     home(true) -- запустить завершающую функцию
  146.     report('insurmountable obstacle', true) -- послать сообщение
  147.   else
  148.     while robot.swing(side) do end -- копать пока возможно
  149.   end
  150.   if robot.move(side) then -- если робот сдвинулся, обновить координаты
  151.     steps = steps + 1 -- debug
  152.     if side == 0 then
  153.       Y = Y-1
  154.     elseif side == 1 then
  155.       Y = Y+1
  156.     elseif side == 3 then
  157.       if D == 0 then
  158.         Z = Z+1
  159.       elseif D == 1 then
  160.         X = X-1
  161.       elseif D == 2 then
  162.         Z = Z-1
  163.       else
  164.         X = X+1
  165.       end
  166.     end
  167.   end
  168.   if not ignore then
  169.     check()
  170.   end
  171. end
  172.  
  173. turn = function(side) -- поворот в сторону
  174.   side = side or false
  175.   if robot.turn(side) and D then -- если робот повернулся, обновить переменную  направления
  176.     turns = turns+1 -- debug
  177.     if side then
  178.       D = (D+1)%4
  179.     else
  180.       D = (D-1)%4
  181.     end
  182.     check()
  183.   end
  184. end
  185.  
  186. smart_turn = function(side) -- поворот в определенную сторону света
  187.   while D ~= side do
  188.     turn((side-D)%4==1)
  189.   end
  190. end
  191.  
  192. go = function(x, y, z) -- переход по указанным координатам
  193.   if border and y < border then
  194.     y = border
  195.   end
  196.   while Y ~= y do
  197.     if Y < y then
  198.       step(1)
  199.     elseif Y > y then
  200.       step(0)
  201.     end
  202.   end
  203.   if X < x then
  204.     smart_turn(3)
  205.   elseif X > x then
  206.     smart_turn(1)
  207.   end
  208.   while X ~= x do
  209.     step(3)
  210.   end
  211.   if Z < z then
  212.     smart_turn(0)
  213.   elseif Z > z then
  214.     smart_turn(2)
  215.   end
  216.   while Z ~= z do
  217.     step(3)
  218.   end
  219. end
  220.  
  221. scan = function(xx, zz) -- сканирование квадрата x8 относительно робота
  222.   local raw, index = geolyzer.scan(xx, zz, -1, 8, 8, 1), 1 -- получить сырые данные, установить индекс в начало таблицы
  223.   for z = zz, zz+7 do -- развертка данных по z
  224.     for x = xx, xx+7 do -- развертка данных по х
  225.       if raw[index] >= min and raw[index] <= max then -- если обнаружен блок с подходящей плотностью
  226.         table.insert(WORLD.x, X+x) --| записать метку в список
  227.         table.insert(WORLD.y, Y-1) --| с коррекцией локальных
  228.         table.insert(WORLD.z, Z+z) --| координат геосканера
  229.       elseif raw[index] < -0.31 then -- если обнаружен блок с отрицательной плотностью
  230.         border = Y -- сделать отметку
  231.       end
  232.       index = index + 1 -- переход к следующему индексу сырых даннх
  233.     end
  234.   end
  235. end
  236.  
  237. calibration = function() -- калибровка при запуске
  238.   if not controller then -- проверить наличие контроллера инвентаря
  239.     report('inventory controller not detected', true)
  240.   elseif not geolyzer then -- проверить наличие геосканера
  241.     report('geolyzer not detected', true)
  242.   elseif not robot.detect(0) then
  243.     report('bottom solid block is not detected', true)
  244.   elseif not robot.durability() then
  245.     report('there is no suitable tool in the manipulator', true)
  246.   end
  247.   local clist = computer.getDeviceInfo()
  248.   for i, j in pairs(clist) do
  249.     if j.description == 'Solar panel' then
  250.       solar = true
  251.       break
  252.     end
  253.   end
  254.   if chunkloader then -- если есть чанклоадер
  255.     chunkloader.setActive(true) -- включить
  256.   end
  257.   if modem then -- если есть модем
  258.     --modem.open(port)
  259.     modem.setWakeMessage('') -- установить сообщение пробуждения
  260.     modem.setStrength(400) -- установить силу сигнала
  261.   elseif tunnel then -- если есть туннель
  262.     tunnel.setWakeMessage('') -- установить сообщение пробуждения
  263.   end
  264.   for slot = 1, inventory do -- пройти по слотам инвентаря
  265.     if robot.count(slot) == 0 then -- если слот пуст
  266.       robot.select(slot) -- выбрать слот
  267.       break
  268.     end
  269.   end
  270.   local energy = computer.energy() -- получить уровень энергии
  271.   step(0) -- сделать шаг
  272.   E_C = math.ceil(energy-computer.energy()) -- записать уровень потребления
  273.   energy = robot.durability() -- получить уровень износа/разряда инструмента
  274.   while energy == robot.durability() do -- пока не обнаружена разница
  275.     robot.place(3) -- установить блок
  276.     robot.swing(3) -- разрушить блок
  277.   end
  278.   W_R = energy-robot.durability() -- записать результат
  279.   local sides = {2, 1, 3, 0} -- линки сторон света, для сырых данных
  280.   D = nil -- обнуление направления
  281.   for s = 1, #sides do -- проверка всех направлений
  282.     if robot.detect(3) or robot.place(3) then -- проверить наличие блока перед носом
  283.       local A = geolyzer.scan(-1, -1, 0, 3, 3, 1) -- сделать первый скан
  284.       robot.swing(3) -- сломать блок
  285.       local B = geolyzer.scan(-1, -1, 0, 3, 3, 1) -- сделать второй скан
  286.       for n = 2, 8, 2 do -- обойти смежные блоки в таблице
  287.         if math.ceil(B[n])-math.ceil(A[n])<0 then -- если блок исчез
  288.           D = sides[n/2] -- установить новое направление
  289.           break -- выйти из цикла
  290.         end
  291.       end
  292.     else
  293.       turn() -- задействовать простой поворот
  294.     end
  295.   end
  296.   if not D then
  297.     report('calibration error', true)
  298.   end
  299. end
  300.  
  301. inv_check = function() -- инвентаризация
  302.   if ignore_check then
  303.     return
  304.   end
  305.   local items = 0
  306.   for slot = 1, inventory do
  307.     if robot.count(slot) > 0 then
  308.       items = items + 1
  309.     end
  310.   end
  311.   if inventory-items < 10 or items/inventory > 0.9 then
  312.     while robot.suck(1) do end
  313.     home(true)
  314.   end
  315. end
  316.  
  317. sorter = function(pack) -- сортировка лута
  318.   robot.swing(0) -- освободить место для мусора
  319.   robot.swing(1) -- освободить место для буфера
  320.   ------- сброс мусора -------
  321.   local empty, available = 0, {} -- создать счетчик пустых слотов и доступных для упаковки
  322.   for slot = 1, inventory do -- пройти по слотам инвентаря
  323.     local item = controller.getStackInInternalSlot(slot) -- получить информацию о предмете
  324.     if item then -- если есть предмет
  325.       local name = item.name:gsub('%g+:', '')
  326.       if tails[name] then -- проверить на совпадение в списке отходов
  327.         robot.select(slot) -- выбрать слот
  328.         robot.drop(0) -- выбросить к отходам
  329.         empty = empty + 1 -- обновить счетчик
  330.       elseif fragments[name] then -- если есть совпадение в списке фрагментов
  331.         if available[name] then -- если уже создан счетчик
  332.           available[name] = available[name] + item.size -- обновить количество
  333.         else -- иначе
  334.           available[name] = item.size -- задать счетчик для имени
  335.         end
  336.       end
  337.     else -- обнаружен пустой слот
  338.       empty = empty + 1 -- обновить счетчик
  339.     end
  340.   end
  341.   -- упаковка предметов в блоки --
  342.   if crafting and (empty < 12 or pack) then -- если есть верстак и меньше 12 свободных слотов или задана принудительная упаковка
  343.     -- перенос лишних предметов в буфер --
  344.     if empty < 10 then -- если пустых слотов меньше 10
  345.       empty = 10-empty -- увеличить количество пустых слотов для обратного отсчета
  346.       for slot = 1, inventory do -- просканировать инвентарь
  347.         local item = controller.getStackInInternalSlot(slot)
  348.         if item then -- если слот не пуст
  349.           if not wlist[item.name] then -- проверка имени, чтобы не выкинуть важный предмет в лаву
  350.             local name = item.name:gsub('%g+:', '') -- отформатировать имя
  351.             if available[name] then -- если есть в счетчике
  352.               available[name] = available[name] - item.size -- обновить счетчик
  353.             end
  354.             robot.select(slot) -- выбрать слот
  355.             robot.drop(1) -- выбросить в буфер
  356.             empty = empty - 1 -- обновить счетчик
  357.           end
  358.         end
  359.         if empty == 0 then -- если место освободилось
  360.           break -- прервать цикл
  361.         end
  362.       end
  363.     end
  364.     ------- основной цикл крафта -------
  365.     for o, m in pairs(available) do
  366.       if m > 8 then
  367.         for l = 1, math.ceil(m/576) do
  368.           inv_check()
  369.           -- очистка рабочей зоны --
  370.           for i = 1, 9 do -- пройти по слотам верстака
  371.             if robot.count(workbench[i]) > 0 then -- если слот не пуст
  372.               robot.select(workbench[i]) -- выбрать слот
  373.               for slot = 4, inventory do -- перебор слотов инвентаря
  374.                 if slot == 4 or slot == 8 or slot > 11 then -- исключить слоты верстака
  375.                   robot.transferTo(slot) -- попробовать переместить предметы
  376.                   if robot.count(slot) == 0 then -- если слот освободился
  377.                     break -- прервать цикл
  378.                   end
  379.                 end
  380.               end
  381.               if robot.count() > 0 then -- если обнаружена перегрузка
  382.                 while robot.suck(1) do end -- забрать предметы из буфера
  383.                 return -- прекратить упаковку
  384.               end
  385.             end
  386.           end
  387.           for slot = 4, inventory do -- цикл поиска фрагментов
  388.             local item = controller.getStackInInternalSlot(slot) -- получить информацию о предмете
  389.             if item and (slot == 4 or slot == 8 or slot > 11) then -- если есть предмет вне рабочей зоны
  390.               if o == item.name:gsub('%g+:', '') then -- если предмет совпадает
  391.                 robot.select(slot) -- при совпадении выбрать слот
  392.                 for n = 1, 10 do -- цикл заполнения рабочей зоны
  393.                   robot.transferTo(workbench[n%9+1], item.size/9) -- разделить текущий стак на 9 частей и перенести в верстак
  394.                 end
  395.                 if robot.count(1) == 64 then -- сброс при заполнении верстака
  396.                   break
  397.                 end
  398.               end
  399.             end
  400.           end
  401.           robot.select(inventory) -- выбор последнего слота
  402.           crafting.craft() -- создание блока
  403.           -- цикл сортировки остатков
  404.           for A = 1, inventory do -- основной проход
  405.             local size = robot.count(A) -- получить количество предметов
  406.             if size > 0 and size < 64 then -- если слот не пуст и не полон
  407.               for B = A+1, inventory do -- проход сравнения
  408.                 if robot.compareTo(B) then -- если предметы одинаковые
  409.                   robot.select(A) -- выбрать слот
  410.                   robot.transferTo(B, 64-robot.count(B)) -- перенести до заполнения
  411.                 end
  412.                 if robot.count() == 0 then -- если слот освободился
  413.                   break -- прервать сравнение
  414.                 end
  415.               end
  416.             end
  417.           end
  418.         end
  419.       end
  420.     end
  421.   end
  422.   while robot.suck(1) do end --- забрать предметы из буфера
  423.   inv_check()
  424. end
  425.  
  426. home = function(forcibly, interrupt) -- переход к начальной точке и сброс лута
  427.   local x, y, z, d
  428.   report('ore unloading')
  429.   ignore_check = true
  430.   local enderchest -- обнулить слот с эндерсундуком
  431.   for slot = 1, inventory do -- просканировать инвентарь
  432.     local item = controller.getStackInInternalSlot(slot) -- получить информацию о слоте
  433.     if item then -- если есть предмет
  434.       if item.name == 'enderstorage:ender_storage' then -- если есть эндерсундук
  435.         enderchest = slot -- задать слот
  436.         break -- прервать поиск
  437.       end
  438.     end
  439.   end
  440.   if enderchest and not forcibly then -- если есть сундук и нет принудительного возвращения домой
  441.     -- step(1) -- подняться на 1 блок
  442.     robot.swing(3) -- освободить место для сундука
  443.     robot.select(enderchest) -- выбрать сундук
  444.     robot.place(3) -- поставить сундук
  445.   else
  446.     x, y, z, d = X, Y, Z, D
  447.     go(0, -2, 0)
  448.     go(0, 0, 0)
  449.   end
  450.   sorter() -- сортировка инвентаря
  451.   local size = nil -- обнулить размер контейнера
  452.   while true do -- войти в бесконечный цикл
  453.     for side = 1, 4 do -- поиск контейнера
  454.       size = controller.getInventorySize(3) -- получение размера инвентаря
  455.       if size and size>26 then -- если контейнер найден
  456.         break -- прервать поиск
  457.       end
  458.       turn() -- повернуться
  459.     end
  460.     if not size or size<26 then -- если контейнер не найден
  461.       report('container not found') -- послать сообщение
  462.       sleep(30)
  463.     else
  464.       break -- продолжить работу
  465.     end
  466.   end
  467.   for slot = 1, inventory do -- обойти весь инвентарь
  468.     local item = controller.getStackInInternalSlot(slot)
  469.     if item then -- если слот не пуст
  470.       if not wlist[item.name] then -- если предмет не в белом списке
  471.         robot.select(slot) -- выбрать слот
  472.         local a, b = robot.drop(3) -- сбросить в контейнер
  473.         if not a and b == 'inventory full' then -- если контейнер заполнен
  474.           while not robot.drop(3) do -- ждать, пока не освободится
  475.             report(b) -- послать сообщение
  476.             sleep(30) -- подождать
  477.           end
  478.         end
  479.       end
  480.     end
  481.   end
  482.   if crafting then -- если есть верстак, забрать предметы из сундука и упаковать
  483.     for slot = 1, size do -- обход слотов контейнера
  484.       local item = controller.getStackInSlot(3, slot) -- получить информацию о пердмете
  485.       if item then -- если есть предмет
  486.         if fragments[item.name:gsub('%g+:', '')] then -- если есть совпадение
  487.           controller.suckFromSlot(3, slot) -- забрать предметы
  488.         end
  489.       end
  490.     end
  491.     sorter(true) -- упаковать
  492.     for slot = 1, inventory do -- обойти весь инвентарь
  493.       local item = controller.getStackInInternalSlot(slot)
  494.       if item then -- если слот не пуст
  495.         if not wlist[item.name] then -- если предмет не в белом списке
  496.           robot.select(slot) -- выбрать слот
  497.           robot.drop(3) -- сбрость в контейнер
  498.         end
  499.       end
  500.     end
  501.   end
  502.   if generator and not forcibly then -- если есть генератор
  503.     for slot = 1, size do -- просканировать контейнер
  504.       local item = controller.getStackInSlot(3, slot) -- получить информацию о пердмете
  505.       if item then -- если есть предмет
  506.         if item.name:sub(11, 15) == 'coal' then -- если в слоте уголь
  507.           controller.suckFromSlot(3, slot) -- взять
  508.           break -- выйти из цикла
  509.         end
  510.       end
  511.     end
  512.   end
  513.   if forcibly then
  514.     report('tool search in container')
  515.     if robot.durability() < 0.3 then -- если прочность инструмента меньше 30%
  516.       robot.select(1) -- выбрать первый слот
  517.       controller.equip() -- поместить инструмент в инвентарь
  518.       local tool = controller.getStackInInternalSlot(1) -- получить данные инструмента
  519.       for slot = 1, size do
  520.         local item = controller.getStackInSlot(3, slot)
  521.         if item then
  522.           if item.name == tool.name and item.damage < tool.damage then
  523.             robot.drop(3)
  524.             controller.suckFromSlot(3, slot)
  525.             break
  526.           end
  527.         end
  528.       end
  529.       controller.equip() -- экипировать
  530.     end
  531.     report('attempt to repair tool')
  532.     if robot.durability() < 0.3 then -- если инструмент не заменился на лучший
  533.       for side = 1, 3 do -- перебрать все стороны
  534.         local name = controller.getInventoryName(3) -- получить имя инвенторя
  535.         if name == 'opencomputers:charger' or name == 'tile.oc.charger' then -- сравнить имя
  536.           robot.select(1) -- выбрать слот
  537.           controller.equip() -- достать инструмент
  538.           if robot.drop(3) then -- если получилось засунуть инструмент в зарядник
  539.             local charge = controller.getStackInSlot(3, 1).charge
  540.             local max_charge = controller.getStackInSlot(3, 1).maxCharge
  541.             while true do
  542.               sleep(30)
  543.               local n_charge = controller.getStackInSlot(3, 1).charge -- получить заряд
  544.               if charge then
  545.                 if n_charge == max_charge then
  546.                   robot.suck(3) -- забрать предмет
  547.                   controller.equip() -- экипировать
  548.                   break -- остановить зарядку
  549.                 else
  550.                   report('tool is '..math.floor((n_charge+1)/max_charge*100)..'% charged')
  551.                 end
  552.               else -- если инструмент не чинится
  553.                 report('tool could not be charged', true) -- остановить работу
  554.               end
  555.             end
  556.           else
  557.             report('tool could not be repaired', true) -- остановить работу
  558.           end
  559.         else
  560.           turn() -- повернуться
  561.         end
  562.       end
  563.       while robot.durability() < 0.3 do
  564.         report('need a new tool')
  565.         sleep(30)
  566.       end
  567.     end
  568.   end
  569.   if enderchest and not forcibly then
  570.     robot.swing(3) -- забрать сундук
  571.   else
  572.     while energy_level() < 0.98 do -- ждать полного заряда батареи
  573.       report('charging')
  574.       sleep(30)
  575.     end
  576.   end
  577.   ignore_check = nil
  578.   if not interrupt then
  579.     report('return to work')
  580.     go(0, -2, 0)
  581.     go(x, y, z)
  582.     smart_turn(d)
  583.   end
  584. end
  585.  
  586. main = function()
  587.   border = nil
  588.   while not border do
  589.     step(0)
  590.     for q = 1, 4 do
  591.       scan(table.unpack(quads[q]))
  592.     end
  593.     check(true)
  594.   end
  595.   while #WORLD.x ~= 0 do
  596.     local n_delta, c_delta, current = math.huge, math.huge
  597.     for index = 1, #WORLD.x do
  598.       n_delta = math.abs(X-WORLD.x[index])+math.abs(Y-WORLD.y[index])+math.abs(Z-WORLD.z[index])-border+WORLD.y[index]
  599.       if (WORLD.x[index] > X and D ~= 3) or
  600.       (WORLD.x[index] < X and D ~= 1) or
  601.       (WORLD.z[index] > Z and D ~= 0) or
  602.       (WORLD.z[index] < Z and D ~= 2) then
  603.         n_delta = n_delta + 1
  604.       end
  605.       if n_delta < c_delta then
  606.         c_delta, current = n_delta, index
  607.       end
  608.     end
  609.     if WORLD.x[current] == X and WORLD.y[current] == Y and WORLD.z[current] == Z then
  610.       remove_point(current)
  611.     else
  612.       local yc = WORLD.y[current]
  613.       if yc-1 > Y then
  614.         yc = yc-1
  615.       elseif yc+1 < Y then
  616.         yc = yc+1
  617.       end
  618.       go(WORLD.x[current], yc, WORLD.z[current])
  619.     end
  620.   end
  621.   sorter()
  622. end
  623.  
  624. calibration() -- запустить калибровку
  625. calibration = nil -- освободить память от функции калибровки
  626. local Tau = computer.uptime() -- записать текущее время
  627. local pos = {0, 0, 0, [0] = 1} -- таблица для хранения координат чанков
  628. for o = 1, 10 do -- цикл ограничения спирали
  629.   for i = 1, 2 do -- цикл обновления координат
  630.     for a = 1, o do -- цикл перехода по линии спирали
  631.       main() -- запуск функции сканирования и добычи
  632.       report('chunk #'..pos[3]+1 ..' processed') -- сообщить о завершении работы в чанке
  633.       pos[i], pos[3] = pos[i] + pos[0], pos[3] + 1 -- обновить координаты
  634.       if pos[3] == chunks then -- если достигнут последний чанк
  635.         home(true, true) -- возврат домой
  636.         report(computer.uptime()-Tau..' seconds\npath length: '..steps..'\nmade turns: '..turns, true) -- сообщить о завершении работы
  637.       else -- иначе
  638.         WORLD = {x = {}, y = {}, z = {}}
  639.         go(pos[1]*16, -2, pos[2]*16) -- перейти к следующему чанку
  640.         go(X, 0, Z) -- перейти в стартовую точку сканирования
  641.       end
  642.     end
  643.   end
  644.   pos[0] = 0-pos[0] -- обновить направление спирали
  645. end
Advertisement
Advertisement
Advertisement
RAW Paste Data Copied
Advertisement