Advertisement
FluttyProger

Untitled

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