Advertisement
Guest User

Untitled

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