Advertisement
bob558

Totoro Recursive Miner

Jul 12th, 2015
265
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Программа копает узкий длинный тоннель. Каждую найденную жилу руды, робот выбирает полностью, используя специальный рекурсивный алгоритм. После того, как жила выработана полностью, робот возвращается обратно, и продолжает копать тоннель.
  2. Робот использует для подзарядки добытый уголь. Когда инвентарь переполняется - он ставит Ender Chest и складывает добытое в него. Затем забирает его и двигается дальше
  3. В начале программы записаны две константы:
  4. INV_SIZE = 24
  5. TECH_SLOTS = 8
  6. INV_SIZE - общее количество слотов в инвентаре
  7. TECH_SLOTS - технические слоты (от начала инвентаря)
  8.  
  9. В технические слоты кладутся образцы пустой породы, которую не надо добывать. Слотов 8, так как GregTech добавляет цветной гранит, а RailCraft - abyssal stone. Обычно в первых слотах лежит: камень, земля, гравий, булыжник, красный гранит, черный гранит, abyssal stone.
  10. В последний, восьмой слот, кладется Ender Chest.
  11.  
  12. Программа принимает два параметра:
  13.  
  14. mine [len] [height]
  15. len - длина тоннеля (по умолчанию - 10)
  16. height - высота (по умолчанию - 4)
  17.  
  18.  
  19.  
  20. -- Totoro Recursive Miner  0.5H --
  21. -- computercraft.ru (c) 01.2015 --
  22. local robot = require('robot')
  23. local event = require('event')
  24. local sides = require('sides')
  25. local computer = require('computer')
  26. local com = require('component')
  27.  
  28. function trytoload(name)
  29.   if com.isAvailable(name) then
  30.     return com.getPrimary(name)
  31.   else
  32.     return nil
  33.   end
  34. end
  35.  
  36. local gen = trytoload("generator")
  37. local cloader = trytoload("chunkloader")
  38.  
  39. TECH_SLOTS = 6
  40. VANILLA_CHEST = true
  41. PATHWAYS = true
  42. DROP_TRASH = false
  43. DEAD_END = 30
  44. USE_CLOADER = true
  45.  
  46. INV_SIZE = robot.inventorySize()
  47. if VANILLA_CHEST then INV_SIZE = math.min(INV_SIZE, TECH_SLOTS + 27) end
  48. MAX = 1024
  49.  
  50. -- statictics
  51. local moves = 0
  52.  
  53. local light_allowed = (robot.setLightColor ~= nil)
  54. local color = {}
  55. color.working = 0x00ff00
  56. color.idle = 0xff0000
  57. color.warning = 0xffff10
  58.  
  59. local trash_slots = TECH_SLOTS - 1
  60. local chest_slot = TECH_SLOTS
  61. local empty_slot = TECH_SLOTS + 1
  62.  
  63. local loc = {x=0, y=0, z=0, d=0}
  64. local lode = {}
  65.  
  66. local a = {...}
  67. local l = tonumber(a[1]) or 22
  68. local w = tonumber(a[2]) or 17
  69. local comeback = a[3] or 'false'
  70. local halfw = math.floor(w/2)
  71.  
  72. if a[1] == '?' or a[1] == '-h' or a[1] == '--help' then
  73.   print("Синтаксис: mine <length> [width] [comeback]")
  74.   return
  75. end
  76. if gen == nil then
  77.   print([[[WARNING] Генератор не обнаружен!\n
  78.     Робот не проработает долго без подзарядки.]])
  79. end
  80. if cloader ~= nil then
  81.   print([[[WARNING] Обнаружен чанклодер!\n
  82.     На сервере ComputerCraft IT 1.7.10 его использование
  83.     приведет к моментальной разрядке батареи!]])
  84. end
  85.  
  86. -- ============================= N A V I G A T I O N ============================= --
  87. function forward()
  88.   if robot.forward() then
  89.     if loc.d == 0 then loc.y = loc.y+1
  90.     elseif loc.d == 1 then loc.x = loc.x+1
  91.     elseif loc.d == 2 then loc.y = loc.y-1
  92.     else loc.x = loc.x-1 end
  93.     moves = moves + 1
  94.     return true
  95.   else
  96.     return false
  97.   end
  98. end
  99. function back()
  100.   if robot.back() then
  101.     if loc.d == 0 then loc.y = loc.y-1
  102.     elseif loc.d == 1 then loc.x = loc.x-1
  103.     elseif loc.d == 2 then loc.y = loc.y+1
  104.     else loc.x = loc.x+1 end
  105.     moves = moves + 1
  106.     return true
  107.   else
  108.     return false
  109.   end
  110. end
  111. function up()
  112.   if robot.up() then
  113.     loc.z = loc.z+1
  114.     moves = moves + 1
  115.     return true
  116.   else
  117.     return false
  118.   end
  119. end
  120. function down()
  121.   if robot.down() then
  122.     loc.z = loc.z-1
  123.     moves = moves + 1
  124.     return true
  125.   else
  126.     return false
  127.   end
  128. end
  129. function turnRight()
  130.   loc.d = (loc.d+1)%4
  131.   robot.turnRight()
  132. end
  133. function turnAround()
  134.   loc.d = (loc.d+2)%4
  135.   robot.turnAround()
  136. end
  137. function turnLeft()
  138.   loc.d = (loc.d+3)%4
  139.   robot.turnLeft()
  140. end
  141.  
  142. -- ========================== F U E L  C O N T R O L ============================= --
  143. function check_fuel()
  144.   if gen ~= nil then
  145.     if (computer.maxEnergy() - computer.energy()) > 1000 then
  146.       if gen.count() == 0 then
  147.         for i=empty_slot, INV_SIZE do
  148.           robot.select(i)
  149.           if gen.insert() then break end
  150.         end
  151.       end
  152.     end
  153.   end
  154. end
  155.  
  156. -- ========================== I T E M  C O N T R O L ============================= --
  157. function check_loot()
  158.   for i=empty_slot, INV_SIZE do
  159.     if robot.count(i) == 0 then return false end
  160.   end
  161.   return true
  162. end
  163.  
  164. function unload()
  165.   -- place for chest
  166.   robot.select(chest_slot)
  167.   while robot.swing() do end
  168.   robot.swingUp()
  169.   up()
  170.   while robot.swing() do end
  171.   down()
  172.   if robot.place() then
  173.     -- put items
  174.     for i=empty_slot, INV_SIZE do
  175.       robot.select(i)
  176.       while robot.drop() do end
  177.     end
  178.  
  179.     -- grab ender chest
  180.     if not VANILLA_CHEST then
  181.       robot.select(chest_slot)
  182.       robot.swing()
  183.     end
  184.   end
  185. end
  186.  
  187. function check_trash()
  188.   for i=1, trash_slots do
  189.     -- if too many trash of this type
  190.     if robot.space(i) == 0 then
  191.       -- drop all but one in trash slot
  192.       robot.select(i)
  193.       robot.dropDown(robot.count(i)-1)
  194.       -- and drop all others
  195.       for j=empty_slot, INV_SIZE do
  196.         if robot.compareTo(j) then
  197.           robot.select(j)
  198.           robot.dropDown()
  199.           robot.select(i)
  200.         end
  201.       end
  202.     end
  203.   end
  204. end
  205.  
  206. -- ================================ M I N I N G ================================== --
  207. function qforward()
  208.   while not forward() do robot.swing() end
  209. end
  210.  
  211. function trash(side)
  212.   for i=1, trash_slots do
  213.     robot.select(i)
  214.     if side == sides.up then
  215.       a,t = robot.detectUp()
  216.       if t ~= 'solid' or robot.compareUp() then return true end
  217.     elseif side == sides.front then
  218.       a,t = robot.detect()
  219.       if t ~= 'solid' or robot.compare() then return true end
  220.     else
  221.       a,t = robot.detectDown()
  222.       if t ~= 'solid' or robot.compareDown() then return true end
  223.     end
  224.   end
  225.   return false
  226. end
  227.  
  228. function mine(side)
  229.   local direct = loc.d
  230.   local backdir = (direct+2)%4
  231.  
  232.   if side == sides.up then
  233.     c = 0
  234.     while not up() do
  235.       robot.swingUp()
  236.       c = c + 1
  237.       if c>DEAD_END then return end
  238.     end
  239.   elseif side == sides.front then
  240.     c = 0
  241.     while not forward() do
  242.       robot.swing()
  243.       c = c + 1
  244.       if c>DEAD_END then return end
  245.     end
  246.   elseif side == sides.down then
  247.     c = 0
  248.     while not down() do
  249.       robot.swingDown()
  250.       c = c + 1
  251.       if c>DEAD_END then return end
  252.     end
  253.   end
  254.  
  255.   lode[loc.x*MAX*MAX + loc.y*MAX + loc.z] = true
  256.  
  257.   -- check further direction
  258.   if lode[loc.x*MAX*MAX + loc.y*MAX + (loc.z+1)] == nil then
  259.     if not trash(sides.up) then mine(sides.up)
  260.     else lode[loc.x*MAX*MAX + loc.y*MAX + (loc.z+1)] = false end
  261.   end
  262.   if lode[loc.x*MAX*MAX + loc.y*MAX + (loc.z-1)] == nil then
  263.     if not trash(sides.down) then mine(sides.down)
  264.     else lode[loc.x*MAX*MAX + loc.y*MAX + (loc.z-1)] = false end
  265.   end
  266.  
  267.   for i=loc.d, loc.d+3 do
  268.     local a = i%4
  269.     local x = loc.x
  270.     local y = loc.y
  271.     if a == 0 then y = y + 1
  272.     elseif a == 1 then x = x + 1
  273.     elseif a == 2 then y = y - 1
  274.     else x = x - 1 end
  275.     if lode[x*MAX*MAX + y*MAX + loc.z] == nil then
  276.       while loc.d < a do turnRight() end
  277.       while loc.d > a do turnLeft() end
  278.       if not trash(sides.front) then mine(sides.front)
  279.       else lode[x*MAX*MAX + y*MAX + loc.z] = false end
  280.     end
  281.   end
  282.  
  283.   -- come back
  284.   if side == sides.up then
  285.     down()
  286.   elseif side == sides.front then
  287.     if loc.d == direct and back() then
  288.       -- yet ready =)
  289.     else
  290.       while loc.d < backdir do turnRight() end
  291.       while loc.d > backdir do turnLeft() end
  292.       qforward()
  293.     end
  294.   elseif side == sides.down then
  295.     up()
  296.   end
  297. end
  298.  
  299. function go(side)
  300.   direct = loc.d
  301.   lode = {}
  302.   mine(side)
  303.   while loc.d < direct do turnRight() end
  304.   while loc.d > direct do turnLeft() end
  305. end
  306.  
  307. function step(progress)
  308.   -- every tenth
  309.   tenth = (loc.x % 15 == 0)
  310.   -- dig one row
  311.   for x=1, w do
  312.     -- check up/down
  313.     if not trash(sides.down) then go(sides.down) end
  314.     if not trash(sides.up) then go(sides.up) end
  315.     -- tonnel for player
  316.     if PATHWAYS then
  317.       if loc.y == halfw then
  318.         robot.swingDown()
  319.         while robot.detectUp() do robot.swingUp() end
  320.       end
  321.       if x == 1 or x == w then
  322.         robot.swingDown()
  323.       end
  324.     else
  325.       if loc.y == halfw then
  326.         robot.swingDown()
  327.       end
  328.     end
  329.     -- move
  330.     if x<w then
  331.       qforward()
  332.       if PATHWAYS and tenth then robot.swingDown() end
  333.     end
  334.   end
  335.  
  336.   -- check front
  337.   if not trash(sides.front) then go(sides.front) end
  338.  
  339.   -- next one
  340.   if progress%2==1 then
  341.     turnRight()
  342.     qforward()
  343.     turnRight()
  344.   else
  345.     turnLeft()
  346.     qforward()
  347.     turnLeft()
  348.   end
  349.  
  350.   -- fuel checking
  351.   check_fuel()
  352.   -- trash checking
  353.   if DROP_TRASH then
  354.     check_trash()
  355.   end
  356.   -- loot checking
  357.   if check_loot() then
  358.     turnAround()
  359.     unload()
  360.     turnAround()
  361.   end
  362. end
  363.  
  364. function goBack()
  365.   while loc.y ~= 0 do
  366.     qforward()
  367.   end
  368.   if loc.d == 0 then turnLeft()
  369.   elseif loc.d == 2 then turnRight() end
  370.   while loc.x ~= 0 do
  371.     qforward()
  372.   end
  373.   turnRight()
  374. end
  375.  
  376. -- =================================== M A I N =================================== --
  377. print("Totoro Recursive Miner 1.5H")
  378. print("[INFO] Запуск. Длина: "..l..". Ширина: "..w..'. \n       Возврат: '..comeback)
  379. if cloader ~= nil and USE_CLOADER then
  380.   cloader.setActive(true)
  381.   print("[INFO] Чанклодер активирован.")
  382. end
  383. print("[INFO] Выключите робота, чтобы прервать работу.")
  384.  
  385. -- statistic value
  386. moves = 0
  387. -- main cycle
  388. robot.turnLeft()
  389. if light_allowed then robot.setLightColor(color.working) end
  390. for i=1, l do
  391.   step(i)
  392. end
  393.  
  394. -- ==================================== E N D ==================================== --
  395. -- move to start position
  396. if comeback == 'true' then goBack() end
  397. if light_allowed then robot.setLightColor(color.idle) end
  398. robot.turnRight()
  399.  
  400. if cloader ~= nil and USE_CLOADER then
  401.   cloader.setActive(false)
  402.   print("[INFO] Чанклодер деактивирован.")
  403. end
  404. print("[STATISTIC] Движений: "..moves)
Advertisement
Advertisement
Advertisement
RAW Paste Data Copied
Advertisement