Advertisement
Andronio12

GeoMiner by Unknown v0.5.1

Mar 27th, 2017
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Original code. https://pastebin.com/xu7Pcj26
  2.  
  3. local shell = require "shell"
  4. local sides = require("sides")
  5. local term = require("term")
  6. local r = require("robot")
  7. local comp = require("component")
  8. local event = require("event")
  9. local computer = require("computer")
  10. local inv = comp.inventory_controller
  11. local KOPALKA = {}
  12. local inv_size = r.inventorySize()
  13. local inv_side = sides.back
  14. local charge_side = sides.left
  15. local battery_side = sides.bottom
  16. local temp_state = {x=0, y=0, z=0, dr=3}
  17. local lc = {x=0, y=0, z=0, dr=3, xMax = 0, zMax = 0}
  18. local way = 0
  19. local ore_count = 0
  20. local warp = false
  21. local bedrockWidth = 5
  22. local back_to_the_future_mode = false
  23. local minHardness = 2.05
  24. local maxHardness = 40
  25. local directives = {
  26.   pause = false,
  27.   home = false,
  28.   report = false,
  29.   move = false    
  30. }
  31.  
  32. local scrap = {
  33.   "minecraft:stone",
  34.   "minecraft:cobblestone",
  35.   "minecraft:dirt",
  36.   "minecraft:gravel",
  37.   "minecraft:sand",
  38.   "minecraft:grass",
  39.   "minecraft:sandstone",
  40.   "minecraft:mossy_cobblestone",
  41.   "minecraft:stonebrick",
  42.   "minecraft:brown_mushroom",
  43.   "minecraft:red_mushroom",
  44.   "minecraft:netherrack"
  45. }
  46.  
  47. local fuel_list = {
  48.   "minecraft:fence",
  49.   "minecraft:planks",
  50.   "minecraft:log",
  51.   "minecraft:coal_block",
  52.   "minecraft:coal"
  53. }
  54.  
  55. local mining_tools_list = {
  56.   "minecraft:iron_pickaxe",
  57.   "minecraft:golden_pickaxe",
  58.   "appliedenergistics2:item.ToolCertusQuartzPickaxe",
  59.   "appliedenergistics2:item.ToolNetherQuartzPickaxe",
  60.   "IC2:itemToolBronzePickaxe",
  61.   "Forestry:bronzePickaxe",
  62.   "minecraft:diamond_pickaxe",
  63.   "IC2:itemToolDrill",
  64.   "IC2:itemToolDDrill",
  65.   "IC2:itemToolIridiumDrill",
  66.   "GraviSuite:advDDrill"
  67. }
  68.  
  69. local function sprintf(s, ...)
  70.   return s:format(...)
  71. end
  72.  
  73. function pause()
  74.   os.sleep(0)
  75. end
  76.  
  77. local function sendSt(message) -- ОТПРАВКА СТАТУСНОГО СООБЩЕНИЯ ЧЕРЕЗ ТУННЕЛЬ
  78.   print(message)
  79.   if warp == true then
  80.     pcall(comp.tunnel.send(message))
  81.   end
  82. end
  83.  
  84. function KOPALKA.duster(tmr)
  85.   while true do
  86.     for i=1,7 do
  87.       local temp = inv.getStackInSlot(3,i)
  88.       if temp then
  89.         if temp.name == "IC2:itemDustSmall" and math.floor(temp.size/9) > 0 then
  90.           for j=1,3 do
  91.             r.select(j)
  92.             inv.suckFromSlot(3,i,math.floor(temp.size/9))
  93.           end
  94.           for j=5,7 do
  95.             r.select(j)
  96.             inv.suckFromSlot(3,i,math.floor(temp.size/9))
  97.           end
  98.           for j=9,11 do
  99.             r.select(j)
  100.             inv.suckFromSlot(3,i,math.floor(temp.size/9))
  101.           end
  102.             r.select(4)
  103.             require("component").crafting.craft(math.floor(temp.size/9))
  104.             r.drop()
  105.         end
  106.       end
  107.     end
  108.     os.sleep(tmr)
  109.   end
  110. end
  111.  
  112. function KOPALKA.charge(charge_side)
  113.   while computer.energy() < (computer.maxEnergy()/2) do
  114.     term.clear()
  115.     KOPALKA.use(charge_side)
  116.     sendSt("Зарядка...")
  117.     os.sleep(60)
  118.     KOPALKA.use(charge_side)
  119.   end
  120.   sendSt("Батарея заряжена")
  121.   return true
  122. end
  123.  
  124. function KOPALKA.charge_tool(chargerSide, slot)
  125.   local side = 3
  126.   local tool = nil
  127.  
  128.   if chargerSide == 1 then
  129.     side=1
  130.   elseif chargerSide == 0 then
  131.     side=0
  132.   end
  133.  
  134.   if r.durability() == nil then
  135.     return false
  136.   end
  137.  
  138.   if r.durability() < 0.3 then
  139.     r.select(slot)
  140.     inv.equip()
  141.     tool = inv.getStackInInternalSlot(slot)
  142.     inv.equip()
  143.     if not(lc.x == 0 and lc.y == 0 and lc.z == 0) then
  144.       return true
  145.     end
  146.   else
  147.     return false
  148.   end
  149.  
  150.   local function isElectric(device)
  151.     if device.maxCharge ~= nil then
  152.       return true
  153.     else
  154.       return false
  155.     end
  156.   end
  157.  
  158.   local function find_new_tool()
  159.     KOPALKA.rot(inv_side)
  160.     local temp = KOPALKA.inv_scaner(mining_tools_list, false, start_slot)
  161.     sendSt("Поиск замены инструменту в сундуке.")
  162.     while temp ~= 0 do
  163.       local temp_device = inv.getStackInSlot(3, temp)
  164.       if isElectric(temp_device) then
  165.         if temp_device.charge/temp_device.maxCharge > 0.6 then
  166.           break
  167.         else
  168.           temp = KOPALKA.inv_scaner(mining_tools_list, false, temp+1)
  169.         end
  170.       else
  171.         if temp_device.damage/temp_device.maxDamage < 0.4 then
  172.           break
  173.         else
  174.           temp = KOPALKA.inv_scaner(mining_tools_list, false, temp+1)
  175.         end
  176.       end
  177.     end
  178.     return temp
  179.   end
  180.  
  181.   local function service(device)
  182.     if isElectric(device) then
  183.       KOPALKA.rot(chargerSide)  
  184.       if not inv.getInventorySize(3) ~= nil then
  185.         sendSt("Зарядник не найден. Установите зарядник.")
  186.         while not inv.getInventorySize(3) ~= nil do
  187.           os.sleep(5)
  188.         end
  189.       end
  190.       r.select(slot)
  191.       inv.equip()
  192.       inv.dropIntoSlot(3,1)
  193.       sendSt("Зарядка инструмента.")
  194.       while inv.getStackInSlot(3,1).charge < device.maxCharge do
  195.         os.sleep(10)
  196.       end
  197.       inv.suckFromSlot(3,1)
  198.       inv.equip()            
  199.     else
  200.       sendSt("Поиск инструмента в сундуке.")
  201.       KOPALKA.rot(inv_side)
  202.       while true do
  203.         local temp = find_new_tool()
  204.         if temp ~= 0 then
  205.           r.select(slot)
  206.           inv.equip()
  207.           if not r.drop() then
  208.             sendSt("Нет места в сундуке. Освободите место.")
  209.             while not r.drop() do
  210.               os.sleep(10)
  211.             end
  212.           end
  213.           inv.suckFromSlot(3, temp)
  214.           inv.equip()
  215.           r.select(1)
  216.           break
  217.         end
  218.       end
  219.     end
  220.   end
  221.  
  222.   if lc.x == 0 and lc.y == 0 and lc.z == 0 then
  223.     sendSt("Сервис инструмента.")
  224.     service(tool)
  225.   else
  226.     return false
  227.   end  
  228. end
  229.  
  230. function KOPALKA.use(s)
  231.   if s == 1 then
  232.     r.useUp()
  233.   elseif s == 2 then
  234.     r.turnAround()
  235.     r.use()
  236.     r.turnAround()
  237.   elseif s == 3 then
  238.     r.use()
  239.   elseif s == 4 then
  240.     r.turnRight()
  241.     r.use()
  242.     r.turnLeft()
  243.   elseif s==5 then
  244.     r.turnLeft()
  245.     r.use()
  246.     r.turnRight()
  247.   else
  248.     r.useDown()
  249.   end
  250. end
  251.  
  252. function KOPALKA.drop() --функция дропа всего инвентаря в сундук, если таковой стоит перед носом
  253.   while true do
  254.     if r.detect() then
  255.       if inv.getInventorySize(3) ~= nil then
  256.         for i=1,inv_size-1 do
  257.           if inv.getStackInInternalSlot(i) ~= nil then
  258.             r.select(i)
  259.             if not r.drop() then
  260.               sendSt("Сундук переполнен. Освободите место под складирование.")
  261.               while not r.drop() do
  262.                 os.sleep(5)
  263.               end
  264.             end
  265.           end
  266.         end
  267.         break
  268.       else
  269.         sendSt("Блок не является сундуком.")
  270.         os.sleep(5)
  271.       end
  272.     else
  273.       sendSt("Установите сундук!")
  274.       os.sleep(5)
  275.     end
  276.   end
  277. end
  278.  
  279. function KOPALKA.isScrap(name) -- ПРОВЕРКА ПРЕДМЕТА, ЯВЛЯЕТСЯ ЛИ ОН МУСОРОМ
  280.   for i, nm in pairs(scrap) do
  281.     if name == nm then  
  282.       return true
  283.     end
  284.   end
  285.   return false
  286. end
  287.  
  288. function KOPALKA.ore_analyze(arg) -- АНАЛИЗ БЛОКА, ЯВЛЯЕТСЯ ЛИ ОН МУСОРОМ
  289.   if arg ~= nil then
  290.     if comp.isAvailable("geolyzer") then
  291.       local lyz = comp.geolyzer
  292.       if KOPALKA.isScrap(lyz.analyze(arg).name) then
  293.         return false
  294.       else
  295.         return true
  296.       end
  297.     else
  298.       print("Геолайзер не обнаружен в системе.")
  299.       return false
  300.     end
  301.   else
  302.     print("Не указан аргумент(сторона проверки).")
  303.   end
  304. end
  305.  
  306. function KOPALKA.drop_scrap()
  307.   for i=1, inv_size do  
  308.     local slot = inv.getStackInInternalSlot(i)
  309.     if slot ~= nil then  
  310.       if KOPALKA.isScrap(slot.name) then
  311.         r.select(i)
  312.         r.dropDown()
  313.       end
  314.     end
  315.   end
  316.   return KOPALKA.inv_sorting()  
  317. end
  318.  
  319.  
  320. -----------------------------------ДВИЖЕНИЕ СКВОЗЬ ПОРОДУ [BEGIN]
  321. local function hiver(a_side) --ДОБЫЧА УЛЬЯ
  322.   if comp.geolyzer.analyze(a_side).name == "ExtraBees:hive" then
  323.     if pcall(r.select, KOPALKA.inv_scaner("Forestry:scoop", true)) then
  324.       inv.equip()
  325.       comp.robot.swing(a_side)
  326.       inv.equip()
  327.       r.select(1)
  328.     end
  329.   end
  330. end
  331.  
  332. function KOPALKA.mUp()
  333.   local try = 1
  334.   repeat
  335.     r.swingUp()
  336.     try = try + 1
  337.     if try >= 15 then
  338.       sendSt("Препятствие у точки: x="..lc.x.." z="..lc.z.." y="..lc.y.." Направление Dr=вверх"..lc.dr)
  339.       local _, det = r.detectUp()
  340.       sendSt(det.." сверху.")
  341.       sendSt(comp.geolyzer.analyze(1).name)
  342.       KOPALKA.mTo(lc.x+2,lc.y,lc.z)
  343.       if not back_to_the_future_mode then
  344.         os.exit(1)
  345.         --KOPALKA.back_to_the_future()
  346.         return false
  347.       else
  348.     try = 1
  349.       end
  350.     elseif try > 12 then
  351.       hiver(1)
  352.     end
  353.   until not r.detectUp()
  354.   while try < 15 and not r.up() do
  355.     r.swingUp()
  356.     try = try + 1
  357.   end
  358.   if try < 15 then
  359.     lc.y = lc.y + 1
  360.     way = way + 1
  361.     return true
  362.    end
  363. end
  364.  
  365. function KOPALKA.mDown(action, arg)
  366.   local try = 1
  367.   if action ~= nil then
  368.     action(arg)
  369.   end
  370.   repeat
  371.     r.swingDown()
  372.     try = try + 1
  373.     if try >= 15 then
  374.       sendSt("Препятствие у точки: x="..lc.x.." z="..lc.z.." y="..lc.y.." Направление Dr= вниз"..lc.dr)
  375.       local _, det = r.detectDown()
  376.       sendSt(det.." снизу.")
  377.       sendSt(comp.geolyzer.analyze(0).name)
  378.       if not back_to_the_future_mode then
  379.         os.exit(1)
  380.         --KOPALKA.back_to_the_future()
  381.         return false
  382.       else
  383.     try = 1
  384.       end
  385.     elseif try > 12 then
  386.       hiver(0)
  387.     end
  388.   until not r.detectDown()
  389.   while try < 15 and not r.down() do
  390.     r.swingDown()
  391.     try = try + 1
  392.   end
  393.   if try < 15 then
  394.     lc.y = lc.y - 1
  395.     way = way + 1
  396.     return true
  397.   end
  398. end
  399.  
  400. function KOPALKA.mForw(action, arg)
  401.   local try = 1
  402.   if action ~= nil then
  403.     action(arg)
  404.   end
  405.   repeat
  406.     r.swing()
  407.     try = try + 1
  408.     if try >= 15 then
  409.       sendSt("Препятствие у точки: x="..lc.x.." z="..lc.z.." y="..lc.y.." Направление Dr="..lc.dr)
  410.       local _, det = r.detect()
  411.       sendSt(det.." спереди.")
  412.       sendSt(comp.geolyzer.analyze(3).name)
  413.       if not back_to_the_future_mode then
  414.         os.exit(1)
  415.         --KOPALKA.back_to_the_future()
  416.         return false
  417.       else
  418.     try = 1
  419.       end
  420.     elseif try > 12 then
  421.       hiver(3)
  422.     end
  423.   until not r.detect()
  424.   while try < 15 and not r.forward() do
  425.     r.swing()
  426.     try = try + 1
  427.   end
  428.   if try < 15 then
  429.     way = way + 1
  430.     if lc.dr==2 then
  431.       lc.x = lc.x - 1
  432.     elseif lc.dr==3 then
  433.       lc.x = lc.x + 1
  434.     elseif lc.dr==4 then
  435.       lc.z = lc.z + 1
  436.     elseif lc.dr==5 then
  437.       lc.z = lc.z - 1
  438.     end
  439.     return true
  440.   end
  441. end
  442. -----------------------------------ДВИЖЕНИЕ СКВОЗЬ ПОРОДУ [END]
  443.  
  444.  
  445. -----------------------------------ВРАЩЕНИЕ К ПРОГРАММНОЙ НАВИГАЦИИ [BEGIN]
  446. function KOPALKA.turnLeft()
  447.   r.turnLeft()
  448.   if lc.dr == 3 then
  449.     lc.dr = 5
  450.   elseif lc.dr == 4 then
  451.     lc.dr = 3
  452.   elseif lc.dr == 2 then
  453.     lc.dr = 4
  454.   elseif lc.dr == 5 then
  455.     lc.dr = 2
  456.   end
  457. end
  458.  
  459. function KOPALKA.turnRight()
  460.   r.turnRight()
  461.   if lc.dr == 3 then
  462.     lc.dr = 4
  463.   elseif lc.dr == 4 then
  464.     lc.dr = 2
  465.   elseif lc.dr == 2 then
  466.     lc.dr = 5
  467.   elseif lc.dr == 5 then
  468.     lc.dr = 3
  469.   end
  470. end
  471.  
  472. function KOPALKA.turnAround()
  473.   r.turnAround()
  474.   if lc.dr == 3 then
  475.     lc.dr = 2
  476.   elseif lc.dr == 4 then
  477.     lc.dr = 5
  478.   elseif lc.dr == 2 then
  479.     lc.dr = 3
  480.   elseif lc.dr == 5 then
  481.     lc.dr = 4
  482.   end
  483. end
  484.  
  485. function KOPALKA.rot(side) -- ВРАЩЕНИЕ С ЗАПОМИНАНИЕМ НАПРАВЛЕНИЯ
  486.   if (side ~= 1) and (side ~= 0) and lc.dr-side ~=0 then
  487.     if lc.dr == 3 then
  488.       if side == 4 then
  489.         KOPALKA.turnRight()
  490.       elseif side == 2 then
  491.         KOPALKA.turnAround()
  492.       elseif side == 5 then
  493.         KOPALKA.turnLeft()
  494.       end
  495.     elseif lc.dr == 4 then
  496.       if side == 2 then
  497.         KOPALKA.turnRight()
  498.       elseif side == 5 then
  499.         KOPALKA.turnAround()
  500.       elseif side == 3 then
  501.         KOPALKA.turnLeft()
  502.       end
  503.     elseif lc.dr == 2 then
  504.       if side == 5 then
  505.         KOPALKA.turnRight()
  506.       elseif side == 3 then
  507.         KOPALKA.turnAround()
  508.       elseif side == 4 then
  509.         KOPALKA.turnLeft()
  510.       end
  511.     else
  512.       if side == 3 then
  513.         KOPALKA.turnRight()
  514.       elseif side == 4 then
  515.         KOPALKA.turnAround()
  516.       elseif side == 2 then
  517.         KOPALKA.turnLeft()
  518.       end
  519.     end
  520.   end
  521. end
  522. -----------------------------------ВРАЩЕНИЕ К ПРОГРАММНОЙ НАВИГАЦИИ [END]
  523.  
  524.  
  525. -----------------------------------ДВИЖЕНИЕ С ПРОГРАММНОЙ НАВИГАЦИЕЙ [BEGIN]
  526. function KOPALKA.mTo(x, y, z, action, arg)
  527.   if directives.pause then
  528.     KOPALKA.execDirective()
  529.   end
  530.   if lc.x > x then
  531.     KOPALKA.rot(sides.back)
  532.     while lc.x > x do
  533.       KOPALKA.mForw(action,arg)
  534.     end
  535.   end
  536.   if lc.x < x then
  537.     KOPALKA.rot(sides.forward)
  538.     while lc.x < x do
  539.       KOPALKA.mForw(action,arg)
  540.     end
  541.   end
  542.   if lc.z > z then
  543.     KOPALKA.rot(sides.left)
  544.     while lc.z > z do
  545.       KOPALKA.mForw(action,arg)
  546.     end  
  547.   end
  548.   if lc.z < z then
  549.     KOPALKA.rot(sides.right)
  550.     while lc.z < z do
  551.       KOPALKA.mForw(action,arg)
  552.     end
  553.   end
  554.   while lc.y > y do
  555.     KOPALKA.mDown(action,arg)
  556.   end
  557.   while lc.y < y do
  558.     KOPALKA.mUp(action,arg)
  559.   end
  560. end
  561.  
  562. function KOPALKA.home(action, arg)
  563.   temp_state.x = lc.x
  564.   temp_state.y = lc.y
  565.   temp_state.z = lc.z
  566.   temp_state.dr = lc.dr
  567.   KOPALKA.mTo(0, 0, 0, action, arg)
  568.   KOPALKA.rot(2)
  569.   KOPALKA.drop_scrap()
  570.   KOPALKA.drop()
  571.   --KOPALKA.rot(3)
  572. end
  573.  
  574. function KOPALKA.back_to_mine(action, arg)
  575.   KOPALKA.mTo(0, temp_state.y, 0, action, arg)
  576.   KOPALKA.mTo(temp_state.x, temp_state.y, temp_state.z, action, arg)
  577.   KOPALKA.rot(temp_state.dr)
  578.   temp_state.x = 0
  579.   temp_state.y = 0
  580.   temp_state.z = 0
  581.   temp_state.dr = 3
  582. end
  583.  
  584. -----------------------------------ДВИЖЕНИЕ С ПРОГРАММНОЙ НАВИГАЦИЕЙ [END]
  585.  
  586.  
  587. function KOPALKA.check_inv()
  588.   return r.inventorySize()
  589. end
  590.  
  591. function KOPALKA.inv_sorting()
  592.   local items_stored = 0
  593.  
  594.   for i=1, inv_size-1 do
  595.     if r.count(i) == 0 then
  596.       for j=inv_size-1, 1, -1 do
  597.         if r.count(j) > 0 then
  598.           if j<i then
  599.             break
  600.           end
  601.           r.select(j)
  602.           r.transferTo(i)
  603.           break
  604.         end
  605.       end
  606.     end
  607.   end
  608.   for i=1,inv_size do
  609.     if r.count(i) > 0 then
  610.       items_stored = items_stored + 1
  611.     end
  612.   end
  613.   r.select(1)
  614.   return items_stored/inv_size
  615. end
  616.  
  617. function KOPALKA.check_state()
  618.   sendSt(sprintf("keep-alive %d", computer.uptime()))
  619.   local need_fuel = computer.energy() < (computer.maxEnergy()*0.90)
  620.  
  621.   local function inventory()
  622.     local need_to_home = false
  623.     if (r.count(inv_size-2) > 0) then  
  624.       if KOPALKA.drop_scrap() > 0.9 then
  625.         need_to_home = true
  626.       else
  627.         need_to_home = false
  628.       end
  629.     end
  630.     return need_to_home
  631.   end
  632.  
  633.   local function fuel(internal)
  634.     local need_to_home = false
  635.     if need_fuel and comp.isAvailable("generator") and comp.generator.count() == 0 then
  636.       local slt = KOPALKA.inv_scaner(fuel_list, internal)
  637.       if slt ~= 0 and not internal then
  638.         r.select(inv_size-2)
  639.         inv.suckFromSlot(3, slt)
  640.         comp.generator.insert()
  641.         r.select(1)
  642.         need_to_home = false
  643.       else
  644.         slt = KOPALKA.inv_scaner(fuel_list, internal)
  645.         if slt ~= 0 and internal then  
  646.           r.select(slt)
  647.           comp.generator.insert()
  648.           r.select(1)
  649.           need_to_home = false
  650.         else
  651.           need_to_home = true
  652.         end
  653.       end
  654.     elseif not comp.isAvailable("generator") and need_fuel then
  655.       need_to_home = true
  656.     end
  657.     return need_to_home
  658.   end
  659.  
  660.   if inventory() or fuel(true) or KOPALKA.charge_tool(charge_side, inv_size-2) then
  661.     KOPALKA.home()
  662.     os.sleep(15)
  663.     KOPALKA.charge_tool(charge_side, inv_size-2)  
  664.     fuel(false)
  665.     KOPALKA.back_to_mine()
  666.   end    
  667. end
  668.  
  669. function KOPALKA.inv_scaner(filter, internal, start_slot) --автопоисковик заданного итема в своем инвентаре по системному имени. возвращает номер ячейки итема, первого найденного от начала ивентаря.
  670.   ins = inv.getInventorySize(3)
  671.   if start_slot == nil then
  672.     start_slot = 1
  673.   end
  674.   if filter == "empty" then
  675.     if internal then
  676.       for i=start_slot, inv_size do
  677.         if inv.getStackInInternalSlot(i) == nil then
  678.           return i
  679.         end
  680.       end
  681.     else
  682.       for i=start_slot, inv.getInventorySize(3) do
  683.         if inv.getStackInSlot(3, i) == nil then
  684.           return i
  685.         end
  686.       end
  687.     end
  688.   end  
  689.   if internal then
  690.     for i=start_slot, inv_size do
  691.       if inv.getStackInInternalSlot(i) ~= nil then
  692.         if pcall(pairs, filter) then
  693.           for j, name in pairs(filter) do
  694.             if inv.getStackInInternalSlot(i).name == name then
  695.               return i
  696.             end
  697.           end
  698.         else
  699.           if inv.getStackInInternalSlot(i).name == filter then
  700.             return i
  701.           end
  702.         end
  703.       end
  704.     end
  705.     return 0  
  706.   else
  707.     if ins ~= nil  then
  708.       for i=start_slot, ins do
  709.         if inv.getStackInSlot(3, i) ~= nil then
  710.           if pcall(pairs, filter) then
  711.             for j, name in pairs(filter) do
  712.               if inv.getStackInSlot(3, i).name == name then
  713.                 return i
  714.               end
  715.             end
  716.           else
  717.             if inv.getStackInSlot(3, i).name == filter then
  718.               return i
  719.             end
  720.           end
  721.         end
  722.       end
  723.       return 0
  724.     else
  725.       return 0
  726.     end
  727.   end
  728. end
  729.  
  730. function KOPALKA.distance(blockA, blockB)
  731.   local dist = math.sqrt(math.pow(blockA.x - blockB.x,2) +
  732.   math.pow(blockA.z - blockB.z,2) + math.pow(blockA.y - blockB.y,2))
  733.   return dist
  734. end
  735.  
  736. function KOPALKA.closest_point(point, points)
  737.   local cl_num = 1
  738.   local length = KOPALKA.distance(point, points[1])
  739.   for i=1, #points do
  740.     local l = KOPALKA.distance(point, points[i])
  741.     if l < length then
  742.       cl_num = i
  743.       length = l
  744.     end
  745.   end
  746.   return cl_num
  747. end
  748.  
  749. function KOPALKA.waypoints(ores_table, last)
  750.   local yeildGuard = 0
  751.   local way_table = {}
  752.   local count = #ores_table
  753.   table.insert(way_table, {x=lc.x, z=lc.z, y=lc.y})
  754.   while count ~= #way_table - 1 do
  755.     yeildGuard = yeildGuard + 1
  756.     if yeildGuard == 100 then
  757.       yeildGuard = 0
  758.       pause()
  759.     end
  760.     local j = KOPALKA.closest_point(way_table[#way_table], ores_table)
  761.     table.insert(way_table, ores_table[j])
  762.     table.remove(ores_table, j)
  763.   end
  764.   return way_table, last
  765. end
  766.  
  767. function KOPALKA.scanVolume(xn, zn, bedrock, side, hight_border) --сканирование карьерного "этажа" заданного радиуса -10 блоков вниз+сканер+10 блоков вверх; bedrock - верхний уровень бедрока
  768.   local geo = comp.geolyzer
  769.   local ores_table = {}
  770.   local last = false
  771.   local x_limit = 0
  772.   local z_limit = 0
  773.   local x_increment = 1
  774.   local z_increment = 1
  775.   if side == "north" or side == "север" then
  776.     x_limit = zn
  777.     x_increment = 1
  778.     z_limit = -xn
  779.     z_increment = -1
  780.   elseif side == "west" or side == "запад" then
  781.     x_limit = -xn
  782.     x_increment = -1
  783.     z_limit = -zn
  784.     z_increment = -1
  785.   elseif side == "south" or side == "юг" then
  786.     x_limit = -zn
  787.     x_increment = -1
  788.     z_limit = xn
  789.     z_increment = 1
  790.    elseif side == "east" or side == "восток" or side == nil then
  791.      x_limit = xn
  792.      x_increment = 1
  793.     z_limit = zn
  794.     z_increment = 1
  795.   end
  796.  
  797.   for xt=0,x_limit,x_increment do
  798.     for zt=0,z_limit,z_increment do
  799.       local scan = geo.scan(xt,zt,true)
  800.       for yt=hight_border+33, 33+math.abs(hight_border) do
  801.         if scan[yt] > minHardness and scan[yt] < maxHardness and ((yt-33)+lc.y) > bedrock then
  802.           if side == "north" or side == "север" then
  803.             table.insert(ores_table, {x=math.abs(zt)+lc.x, z=math.abs(xt)+lc.z, y=(yt-33)+lc.y})
  804.           elseif side == "west" or side == "запад" then
  805.             table.insert(ores_table, {x=math.abs(xt)+lc.x, z=math.abs(zt)+lc.z, y=(yt-33)+lc.y})
  806.           elseif side == "south" or side == "юг" then
  807.             table.insert(ores_table, {x=math.abs(zt)+lc.x, z=math.abs(xt)+lc.z, y=(yt-33)+lc.y})
  808.           elseif side == "east" or side == "восток" or side == nil then
  809.             table.insert(ores_table, {x=math.abs(xt)+lc.x, z=math.abs(zt)+lc.z, y=(yt-33)+lc.y})
  810.           end    
  811.         end
  812.       end
  813.     end
  814.   end
  815.   return ores_table
  816. end
  817.  
  818. function KOPALKA.whatsSide()
  819.   local geo = comp.geolyzer
  820.   local function isBlock(dens)
  821.     if dens ~= nil and dens ~= 0 then
  822.       return 1
  823.     elseif dens == 0 then
  824.       return 0
  825.     end
  826.   end
  827.  
  828.   local function check(fig, front)
  829.     local figure1 = {
  830.       east = isBlock(geo.scan(1,0)[33]),
  831.       south = isBlock(geo.scan(0,1)[33]),
  832.       west = isBlock(geo.scan(-1,0)[33]),  
  833.       north = isBlock(geo.scan(0,-1)[33])
  834.     }  
  835.     if front then
  836.       if fig.east > figure1.east  then
  837.         return "east"
  838.       elseif fig.south > figure1.south then
  839.         return "south"
  840.       elseif fig.west > figure1.west then
  841.         return "west"
  842.       elseif fig.north > figure1.north then
  843.         return "north"
  844.       end
  845.     elseif not front then
  846.       if fig.east < figure1.east  then
  847.         return "east"
  848.       elseif fig.south < figure1.south then
  849.         return "south"
  850.       elseif fig.west < figure1.west then
  851.         return "west"
  852.       elseif fig.north < figure1.north then
  853.         return "north"
  854.       end  
  855.     end
  856.   end
  857.   local figure = {
  858.     east = isBlock(geo.scan(1,0)[33]),
  859.     south = isBlock(geo.scan(0,1)[33]),
  860.     west = isBlock(geo.scan(-1,0)[33]),  
  861.     north = isBlock(geo.scan(0,-1)[33])
  862.   }
  863.   KOPALKA.rot(3)
  864.   while true do
  865.     if r.detect() then
  866.       r.swing()
  867.       local direction = check(figure, true)
  868.       r.place()
  869.       return direction
  870.     elseif r.detectDown() then
  871.       r.swingDown()
  872.       r.place()
  873.       local direction = check(figure, false)
  874.       r.swing()
  875.       r.placeDown()
  876.       return direction
  877.     end
  878.     sendSt("Для ориентирования в пространстве недостаточно данных.")
  879.     sendSt("Пожалуйста установите любой блок перед или под роботом и повторите попытку")
  880.     os.exit(1)
  881.   end
  882. end
  883.  
  884. function KOPALKA.findoutBedrockLevel() -- нижний уровень бедрока
  885.   local bedrock = -1
  886.   local start_level = lc.y
  887.   local geo = comp.geolyzer
  888.   local function scan()
  889.     local tempr=geo.scan(0,0)
  890.     for i = 10, 1, -1 do
  891.       if tempr[33 - i] < -0.3 then
  892.         return lc.y - i, true
  893.       end
  894.     end
  895.     return 0, false
  896.   end
  897.   for i = lc.y, -256, -10 do
  898.     local bed, catch = scan()
  899.     if not catch then
  900.       KOPALKA.mTo(lc.x, i, lc.z)
  901.     else
  902.       bedrock = bed
  903.       break
  904.     end
  905.   end
  906.   KOPALKA.mTo(lc.x, start_level, lc.z)
  907.   return bedrock
  908. end
  909.  
  910. function KOPALKA.clusterDigger(start_point, x, z, bedrock, side)
  911.   sendSt(sprintf("cluster: %d %d %d (%d %d %d) %s", start_point.x, start_point.y, start_point.z, x, bedrock, z, side))
  912.   sendSt("Сканирование заданного объема, может занять несколько минут...")
  913.   if side == nil then
  914.     side = KOPALKA.whatsSide()
  915.   end
  916.   if start_point == nil then
  917.     start_point = lc
  918.   end
  919.   KOPALKA.mTo(start_point.x, start_point.y, start_point.z)
  920.   for Y=lc.y, bedrock+bedrockWidth+1, -1 do
  921.     if Y%21 == 0 or Y == bedrock + 9 then
  922.       KOPALKA.mTo(start_point.x, Y, start_point.z)
  923.       KOPALKA.rot(3)
  924.       arr=KOPALKA.waypoints(KOPALKA.scanVolume(x-1,z-1, bedrock+bedrockWidth-1, side, -11))
  925.       ore_count = ore_count + (#arr-1)
  926.       for i=1, #arr do
  927.         KOPALKA.mTo(arr[i].x, arr[i].y, arr[i].z)
  928.         if i%10 == 0 then
  929.           KOPALKA.check_state()
  930.         end
  931.         if way%30 == 0 then
  932.           KOPALKA.check_state()
  933.         end
  934.       end
  935.     end
  936.   end
  937. end
  938.  
  939. function KOPALKA.geoMiner(x, z, bedrock, side, x_lim, z_lim)
  940.   if bedrock == nil then
  941.     sendSt("Проверка уровня бедрока. Вертикальная шахта до дна и обратно.")
  942.     bedrock = KOPALKA.findoutBedrockLevel()
  943.   end
  944.   sendSt(sprintf("bedrock= %d\n", bedrock))
  945.   local start_point = {x=0, y=0, z=0}
  946.   local x_limit = x_lim
  947.   local z_limit = z_lim
  948.   if x_lim == nil then
  949.     x_limit = 32
  950.   end
  951.   if z_lim == nil then
  952.     z_limit = 32
  953.   end
  954.   if side == nil then
  955.     side = KOPALKA.whatsSide()
  956.   end
  957.  
  958.   local function z_glide()
  959.     if z/z_limit < 1 then
  960.       KOPALKA.clusterDigger(start_point, x_limit, z, bedrock, side)
  961.     else
  962.       for j=1, math.floor(z/z_limit) do
  963.         KOPALKA.clusterDigger(start_point, x_limit, z_limit, bedrock, side)
  964.         start_point.z = j*z_limit+1
  965.       end
  966.       if z%z_limit > 0 then
  967.         KOPALKA.clusterDigger(start_point, x_limit, z%z_limit, bedrock, side)
  968.       end
  969.       start_point.z = 0
  970.     end
  971.   end
  972.  
  973.   if x/x_limit < 1 then
  974.     local temp = x_limit
  975.     x_limit = x
  976.     z_glide()
  977.     x_limit = temp
  978.   else
  979.     for i=1, math.floor(x/x_limit) do
  980.       z_glide()
  981.       start_point.x = i*x_limit+1
  982.     end
  983.     if x%x_limit > 0 then
  984.       x_limit = x%x_limit
  985.       z_glide()
  986.     end
  987.   end
  988.   KOPALKA.home()
  989.   KOPALKA.rot(3)
  990.   sendSt("Итого руды добыто: "..ore_count)
  991.   sendSt("Всего блоков пройдено: "..way)
  992.   sendSt('Робот '..r.name()..' завершил работу.')
  993. end
  994.  
  995. function KOPALKA.check_components()
  996.   local function stop()
  997.     print('> ')
  998.     if tonumber(io.read()) ~= 1 then
  999.       os.exit()
  1000.     end
  1001.   end
  1002.   if comp.isAvailable("tunnel") then
  1003.     warp = true
  1004.     print("\t Связанная карта....доступна.")
  1005.   else
  1006.     print("\t Связанная карта не обнаружена. Начать работу? (0/1)")
  1007.     stop()
  1008.   end
  1009.   if comp.isAvailable("chunkloader") then
  1010.     comp.chunkloader.setActive(true)
  1011.     print("\t Чанклоадер....доступен.")
  1012.   else
  1013.     print("\t Чанклоадер не обнаружен, возможны проблемы и ошибки. Начать работу без чанклоадера? (0/1)")
  1014.     stop()
  1015.   end
  1016.   if comp.isAvailable("inventory_controller") then
  1017.     print("\t Контроллер инвентаря....доступен.")
  1018.   else
  1019.     print("\t Контроллер инвентаря не обнаружен, возможны проблемы и ошибки. Принудительная остановка программы.")
  1020.     os.exit()
  1021.   end
  1022.   if comp.isAvailable("generator") then
  1023.     print("\t Генератор....доступен.")
  1024.   else
  1025.     print("\t Генератор не обнаружен, возможны проблемы и ошибки. Начать работу без генератора? (0/1)")
  1026.     stop()
  1027.   end
  1028.   if comp.isAvailable("geolyzer") then
  1029.     print("\t Геосканер....доступен.")
  1030.   else
  1031.     print("\t Геосканер не обнаружен, возможны проблемы и ошибки. Принудительная остановка программы.")
  1032.     os.exit()
  1033.   end
  1034.   if pcall(r.select,KOPALKA.inv_scaner("Forestry:scoop", true)) then
  1035.     r.transferTo(inv_size)
  1036.     r.select(1)
  1037.     print("\t Сачок....доступен.")
  1038.   else
  1039.     print("\t Сачок не обнаружен, возможны проблемы и ошибки. Начать работу без сачка?")
  1040.     stop()
  1041.   end
  1042.   if r.durability() ~= nil then
  1043.     print("\t Инструмент....доступен.")
  1044.   else
  1045.     print("\t Инструмент не обнаружен, возможны проблемы и ошибки. Принудительная остановка программы.")
  1046.     os.exit()
  1047.   end
  1048.   print("\n Все компоненты в наличии.\n Программа может быть запущена.")
  1049. end
  1050.  
  1051. function KOPALKA.mine(x, z, bedrock, side, x_lim, z_lim)
  1052.   KOPALKA.check_components()
  1053.   lc.xMax = x
  1054.   lc.zMax = z
  1055.   way = 0
  1056.   term.clear()
  1057.   sendSt("Старт карьера: "..x.."x"..z.." блоков.")
  1058.   KOPALKA.check_state()
  1059.   local side = KOPALKA.whatsSide()
  1060.   local ok, err = pcall(KOPALKA.geoMiner, x, z, bedrock, side, x_lim, z_lim)
  1061.   if not ok then
  1062.     if type(err) ~= "table" then
  1063.       sendSt(err)
  1064.     end
  1065.     back_to_the_future_mode = true
  1066.     sendSt('Ошибка/препятствие. Возврат робота.')
  1067.     KOPALKA.mTo(lc.x, 0, lc.z)
  1068.     KOPALKA.home()
  1069.     KOPALKA.rot(3)
  1070.   end
  1071. end
  1072.  
  1073. function main(tArgs, options)
  1074.   local function argNumber(x)
  1075.     local v = tonumber(x)
  1076.     if type(v) ~= 'number' then
  1077.       io.write("Аргументы должны быть заданы в виде чисел.\n")
  1078.       os.exit(1)
  1079.     end
  1080.     return v
  1081.   end
  1082.  
  1083.   local function getNumberOption(name)
  1084.     local v = options[name]
  1085.     if v then
  1086.       v = argNumber(v)
  1087.     end
  1088.     return v
  1089.   end
  1090.  
  1091.   if #tArgs == 2 then
  1092.     bedrockWidth = getNumberOption("bedrock-width") or bedrockWidth
  1093.     minHardness = getNumberOption("min-hardness") or minHardness
  1094.     maxHardness = getNumberOption("max-hardness") or maxHardness
  1095.     local x = argNumber(tArgs[1])
  1096.     local z = argNumber(tArgs[2])
  1097.     KOPALKA.mine(x, z, getNumberOption("bedrock"))
  1098.   else
  1099.     io.write("Запуск: kopalka размер_вперёд размер_справа\n")
  1100.     io.write("Опции:\n")
  1101.     io.write("--min-hardness=<мин. плотность>\n")
  1102.     io.write("--max-hardness=<макс. плотность>\n")
  1103.     io.write("--bedrock=<нижний уровень бедрока относительно робота> ")
  1104.     io.write("= высота_нижнего_слоя_бедрока-высота_на_которой_стоит_робот> - \n")
  1105.     io.write("--bedrock-width=<ширина слоя бедрока>\n")
  1106.     io.write("Робот будет добывать блоки,\nплотность которых находится \nв интервале (<мин. плотность>, <макс. плотность>).\n")
  1107.     io.write("Значение по умолчанию: ("..minHardness..", "..maxHardness..").\n")
  1108.   end
  1109. end
  1110.  
  1111. main(shell.parse(...))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement