Advertisement
bob558

Totoro Recursive Miner

Jul 12th, 2015
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.91 KB | None | 0 0
  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
Add Comment
Please, Sign In to add comment
Advertisement