Advertisement
Tikinashn

LUAMINER_V2

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