Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- FORKED FROM http://pastebin.com/gqZ1Qdqi
- -- http://computercraft.ru/topic/1031-geokopatel-ili-stan-millionerom/
- -- v0.7.6
- ---------------------------------------------------------
- local energyGenPercent = 50
- local energyReturnPercent = 20
- local energyStartPercent = 99
- local minHardness = 2.05
- local maxHardness = 40
- local scanRadius = 5
- local bedrockWidth = 5
- local maxTry = 255
- local chkPeriod = 30
- local scrap = {
- "minecraft:stone",
- "minecraft:cobblestone",
- "minecraft:dirt",
- "minecraft:gravel",
- "minecraft:sand",
- "minecraft:grass",
- "minecraft:sandstone",
- "minecraft:mossy_cobblestone",
- "minecraft:stonebrick",
- "minecraft:brown_mushroom",
- "minecraft:red_mushroom",
- "minecraft:netherrack"
- }
- local fuel_list = {
- "minecraft:fence",
- "minecraft:planks",
- "minecraft:log",
- "minecraft:coal_block",
- "minecraft:coal"
- }
- local mining_tools_list = {
- "minecraft:iron_pickaxe",
- "minecraft:golden_pickaxe",
- "appliedenergistics2:item.ToolCertusQuartzPickaxe",
- "appliedenergistics2:item.ToolNetherQuartzPickaxe",
- "IC2:itemToolBronzePickaxe",
- "Forestry:bronzePickaxe",
- "minecraft:diamond_pickaxe",
- "IC2:itemToolDrill",
- "IC2:itemToolDDrill",
- "IC2:itemToolIridiumDrill",
- "GraviSuite:advDDrill"
- }
- ---------------------------------------------------------
- local shell = require "shell"
- local sides = require("sides")
- local term = require("term")
- local r = require("robot")
- local comp = require("component")
- local event = require("event")
- local computer = require("computer")
- local inv = comp.inventory_controller
- local geolyzer
- local KOPALKA = {}
- local inv_size = r.inventorySize()
- local inv_side = sides.back
- local charge_side = sides.left
- local temp_state = {x=0, y=0, z=0, dr=3}
- local lc = {x=0, y=0, z=0, dr=3, xMax = 0, zMax = 0}
- local way = 0
- local warp = false
- local MINE, BACK_TO_BASE, BACK_TO_MINE, EMERGENCY = 0, 1, 2, 3
- local mode = MINE
- local directives = {
- pause = false,
- home = false,
- report = false,
- move = false
- }
- local progress
- --RoboCraft-server
- if computer.maxEnergy() >= 1000000 then
- print("RoboCraft server detected")
- energyStartPercent = 20
- energyGenPercent = 10
- energyReturnPercent = 2
- end
- local clusterHeight --вычисляется при запуске
- local worldHeight = 256
- local function sprintf(s, ...)
- return s:format(...)
- end
- function pause()
- os.sleep(0)
- end
- local function sendSt(message) -- ОТПРАВКА СТАТУСНОГО СООБЩЕНИЯ ЧЕРЕЗ ТУННЕЛЬ
- if warp then
- pcall(comp.tunnel.send(message))
- end
- end
- local function printSt(message) -- ОТПРАВКА СТАТУСНОГО СООБЩЕНИЯ ЧЕРЕЗ ТУННЕЛЬ
- print(message)
- sendSt(message)
- end
- local actionCnt = 0
- local function incActionCnt(energyOnly)
- -- не проверяем состояние в режимах возврата на базу
- if (mode == EMERGENCY) or (mode == BACK_TO_BASE) then
- return
- end
- if actionCnt%chkPeriod == 0 then
- if energyOnly then
- KOPALKA.check_state(false, false, true)
- else
- KOPALKA.check_state(true, true, true)
- end
- end
- actionCnt = actionCnt + 1
- end
- -- function KOPALKA.duster(tmr)
- -- while true do
- -- for i=1,7 do
- -- local temp = inv.getStackInSlot(3,i)
- -- if temp then
- -- if temp.name == "IC2:itemDustSmall" and math.floor(temp.size/9) > 0 then
- -- for j=1,3 do
- -- r.select(j)
- -- inv.suckFromSlot(3,i,math.floor(temp.size/9))
- -- end
- -- for j=5,7 do
- -- r.select(j)
- -- inv.suckFromSlot(3,i,math.floor(temp.size/9))
- -- end
- -- for j=9,11 do
- -- r.select(j)
- -- inv.suckFromSlot(3,i,math.floor(temp.size/9))
- -- end
- -- r.select(4)
- -- require("component").crafting.craft(math.floor(temp.size/9))
- -- r.drop()
- -- end
- -- end
- -- end
- -- os.sleep(tmr)
- -- end
- -- end
- function KOPALKA.charge_tool(chargerSide, slot)
- local side = 3
- local tool = nil
- if chargerSide == 1 then
- side=1
- elseif chargerSide == 0 then
- side=0
- end
- if r.durability() == nil then
- return false
- end
- if r.durability() < 0.3 then
- r.select(slot)
- inv.equip()
- tool = inv.getStackInInternalSlot(slot)
- inv.equip()
- if not(lc.x == 0 and lc.y == 0 and lc.z == 0) then
- return true
- end
- else
- return false
- end
- local function isElectric(device)
- if device.maxCharge ~= nil then
- return true
- else
- return false
- end
- end
- local function find_new_tool()
- KOPALKA.rot(inv_side)
- local temp = KOPALKA.inv_scaner(mining_tools_list, false, start_slot)
- printSt("Поиск замены инструменту в сундуке.")
- while temp ~= 0 do
- local temp_device = inv.getStackInSlot(3, temp)
- if isElectric(temp_device) then
- if temp_device.charge/temp_device.maxCharge > 0.6 then
- break
- else
- temp = KOPALKA.inv_scaner(mining_tools_list, false, temp+1)
- end
- else
- if temp_device.damage/temp_device.maxDamage < 0.4 then
- break
- else
- temp = KOPALKA.inv_scaner(mining_tools_list, false, temp+1)
- end
- end
- end
- return temp
- end
- local function service(device)
- if isElectric(device) then
- KOPALKA.rot(chargerSide)
- if (inv.getInventorySize(3) or 0) == 0 then
- printSt("Зарядник не найден. Установите зарядник.")
- while (inv.getInventorySize(3) or 0) == 0 do
- os.sleep(5)
- end
- end
- r.select(slot)
- inv.equip()
- inv.dropIntoSlot(3,1)
- printSt("Зарядка инструмента.")
- while inv.getStackInSlot(3,1).charge < device.maxCharge do
- os.sleep(10)
- end
- inv.suckFromSlot(3,1)
- inv.equip()
- else
- printSt("Поиск инструмента в сундуке.")
- KOPALKA.rot(inv_side)
- while true do
- local temp = find_new_tool()
- if temp ~= 0 then
- r.select(slot)
- inv.equip()
- if not r.drop() then
- printSt("Нет места в сундуке. Освободите место.")
- while not r.drop() do
- os.sleep(10)
- end
- end
- inv.suckFromSlot(3, temp)
- inv.equip()
- r.select(1)
- break
- end
- end
- end
- end
- if lc.x == 0 and lc.y == 0 and lc.z == 0 then
- printSt("Сервис инструмента.")
- service(tool)
- else
- return false
- end
- end
- -- function KOPALKA.use(s)
- -- if s == 1 then
- -- r.useUp()
- -- elseif s == 2 then
- -- r.turnAround()
- -- r.use()
- -- r.turnAround()
- -- elseif s == 3 then
- -- r.use()
- -- elseif s == 4 then
- -- r.turnRight()
- -- r.use()
- -- r.turnLeft()
- -- elseif s==5 then
- -- r.turnLeft()
- -- r.use()
- -- r.turnRight()
- -- else
- -- r.useDown()
- -- end
- -- end
- function KOPALKA.drop() --функция дропа всего инвентаря в сундук, если таковой стоит перед носом
- while true do
- if r.detect() then
- if inv.getInventorySize(3) ~= nil then
- for i=1,inv_size-1 do
- if inv.getStackInInternalSlot(i) ~= nil then
- r.select(i)
- if not r.drop() then
- printSt("Сундук переполнен. Освободите место под складирование.")
- while not r.drop() do
- os.sleep(5)
- end
- end
- end
- end
- break
- else
- printSt("Блок не является сундуком.")
- os.sleep(5)
- end
- else
- printSt("Установите сундук!")
- os.sleep(5)
- end
- end
- end
- function KOPALKA.isScrap(name) -- ПРОВЕРКА ПРЕДМЕТА, ЯВЛЯЕТСЯ ЛИ ОН МУСОРОМ
- for i, nm in pairs(scrap) do
- if name == nm then
- return true
- end
- end
- return false
- end
- -- function KOPALKA.ore_analyze(arg) -- АНАЛИЗ БЛОКА, ЯВЛЯЕТСЯ ЛИ ОН МУСОРОМ
- -- if arg ~= nil then
- -- if comp.isAvailable("geolyzer") then
- -- local lyz = comp.geolyzer
- -- if KOPALKA.isScrap(lyz.analyze(arg).name) then
- -- return false
- -- else
- -- return true
- -- end
- -- else
- -- print("Геолайзер не обнаружен в системе.")
- -- return false
- -- end
- -- else
- -- print("Не указан аргумент(сторона проверки).")
- -- end
- -- end
- local dont_drop_scrap
- function KOPALKA.drop_scrap()
- if dont_drop_scrap then
- return
- end
- for i=1, inv_size do
- local slot = inv.getStackInInternalSlot(i)
- if slot ~= nil then
- if KOPALKA.isScrap(slot.name) then
- r.select(i)
- r.dropDown()
- end
- end
- end
- return KOPALKA.inv_sorting()
- end
- -----------------------------------ДВИЖЕНИЕ СКВОЗЬ ПОРОДУ [BEGIN]
- local compR = comp.robot
- if (maxTry or 0 ) < 1 then
- maxTry = 255
- end
- local function hiver(direction) --ДОБЫЧА УЛЬЯ
- if geolyzer and geolyzer.analyze(direction).name == "ExtraBees:hive" then
- if pcall(r.select, KOPALKA.inv_scaner("Forestry:scoop", true)) then
- inv.equip()
- compR.swing(direction)
- inv.equip()
- r.select(1)
- end
- return true
- end
- end
- local function move(direction)
- while true do
- local ok, err = compR.move(direction)
- if not ok and err == "already moving" then
- os.sleep(0.5)
- else
- return ok, err
- end
- end
- end
- function KOPALKA.swingmove(direction, doMove, action, arg)
- if action ~= nil then
- action(arg)
- end
- local detected, detectInf, moveOk, moveInf, rSwing, tSwing
- local chkHiver = true
- for try = 1, maxTry do
- detected, detectInf = compR.detect(direction)
- if detected then
- incActionCnt()
- rSwing, tSwing = compR.swing(direction) --air, block, entity
- if not rSwing and (tSwing ~= "air") then
- local skipErr
- if tSwing == "block" and chkHiver then
- if hiver(direction) then
- chkHiver = false
- skipErr = true
- end
- end
- if not skipErr then
- return false, detectInf, "Неустранимое препятствие ("..tostring(tSwing)..")"
- end
- end
- else
- if doMove then
- incActionCnt()
- moveOk, moveInf = move(direction)
- if moveOk then
- way = way + 1
- return true
- elseif moveInf == "impossible move" then -- or moveInf == "not enough energy"
- return false, detectInf, "Ошибка перемещения ("..tostring(moveInf)..")"
- end
- else
- return true
- end
- end
- end
- return false, detectInf, "Лимит попыток передвижения исчерпан"
- end
- local function makeMoveErrMsg(direction, detect, msg)
- local directionText
- local s = msg.." у точки: x="..lc.x.." z="..lc.z.." y="..lc.y
- if direction == sides.front then
- directionText = "спереди"
- elseif direction == sides.top then
- directionText = "сверху"
- elseif direction == sides.bottom then
- directionText = "снизу"
- else
- directionText = "("..direction..")"
- end
- if geolyzer then
- detect = detect.." ["..geolyzer.analyze(3).name.."]"
- end
- return s.." Направление Dr="..lc.dr.." "..detect.." "..directionText
- end
- function KOPALKA.mUp(action, arg)
- local ok, detect, msg = KOPALKA.swingmove(sides.up, true, action, arg)
- if ok then
- lc.y = lc.y + 1
- else
- printSt(makeMoveErrMsg(sides.down, detect, msg))
- -- KOPALKA.mTo(lc.x+2,lc.y,lc.z) --?? Нужно ли? Совместимость с ЧЛ DA?
- if mode ~= EMERGENCY then -- в режиме аварийного возврата долбимся до упора
- os.exit(1)
- else
- os.sleep(1)
- end
- end
- end
- function KOPALKA.mDown(action, arg)
- local ok, detect, msg = KOPALKA.swingmove(sides.down, true, action, arg)
- if ok then
- lc.y = lc.y - 1
- else
- printSt(makeMoveErrMsg(sides.down, detect, msg))
- if mode ~= EMERGENCY then -- в режиме аварийного возврата долбимся до упора
- os.exit(1)
- else
- os.sleep(1)
- end
- end
- end
- function KOPALKA.mForw(action, arg)
- local ok, detect, msg = KOPALKA.swingmove(sides.front, true, action, arg)
- if ok then
- if lc.dr==2 then
- lc.x = lc.x - 1
- elseif lc.dr==3 then
- lc.x = lc.x + 1
- elseif lc.dr==4 then
- lc.z = lc.z + 1
- elseif lc.dr==5 then
- lc.z = lc.z - 1
- end
- else
- printSt(makeMoveErrMsg(sides.front, detect, msg))
- if mode ~= EMERGENCY then -- в режиме аварийного возврата долбимся до упора
- os.exit(1)
- else
- os.sleep(1)
- end
- end
- end
- -----------------------------------ДВИЖЕНИЕ СКВОЗЬ ПОРОДУ [END]
- -----------------------------------ВРАЩЕНИЕ К ПРОГРАММНОЙ НАВИГАЦИИ [BEGIN]
- function KOPALKA.turnLeft()
- r.turnLeft()
- if lc.dr == 3 then
- lc.dr = 5
- elseif lc.dr == 4 then
- lc.dr = 3
- elseif lc.dr == 2 then
- lc.dr = 4
- elseif lc.dr == 5 then
- lc.dr = 2
- end
- end
- function KOPALKA.turnRight()
- r.turnRight()
- if lc.dr == 3 then
- lc.dr = 4
- elseif lc.dr == 4 then
- lc.dr = 2
- elseif lc.dr == 2 then
- lc.dr = 5
- elseif lc.dr == 5 then
- lc.dr = 3
- end
- end
- function KOPALKA.turnAround()
- r.turnAround()
- if lc.dr == 3 then
- lc.dr = 2
- elseif lc.dr == 4 then
- lc.dr = 5
- elseif lc.dr == 2 then
- lc.dr = 3
- elseif lc.dr == 5 then
- lc.dr = 4
- end
- end
- function KOPALKA.rot(side) -- ВРАЩЕНИЕ С ЗАПОМИНАНИЕМ НАПРАВЛЕНИЯ
- if (side ~= 1) and (side ~= 0) and lc.dr-side ~=0 then
- if lc.dr == 3 then
- if side == 4 then
- KOPALKA.turnRight()
- elseif side == 2 then
- KOPALKA.turnAround()
- elseif side == 5 then
- KOPALKA.turnLeft()
- end
- elseif lc.dr == 4 then
- if side == 2 then
- KOPALKA.turnRight()
- elseif side == 5 then
- KOPALKA.turnAround()
- elseif side == 3 then
- KOPALKA.turnLeft()
- end
- elseif lc.dr == 2 then
- if side == 5 then
- KOPALKA.turnRight()
- elseif side == 3 then
- KOPALKA.turnAround()
- elseif side == 4 then
- KOPALKA.turnLeft()
- end
- else
- if side == 3 then
- KOPALKA.turnRight()
- elseif side == 4 then
- KOPALKA.turnAround()
- elseif side == 2 then
- KOPALKA.turnLeft()
- end
- end
- end
- end
- -----------------------------------ВРАЩЕНИЕ К ПРОГРАММНОЙ НАВИГАЦИИ [END]
- -----------------------------------ДВИЖЕНИЕ С ПРОГРАММНОЙ НАВИГАЦИЕЙ [BEGIN]
- function KOPALKA.mTo(x, y, z, action, arg)
- if directives.pause then
- KOPALKA.execDirective()
- end
- if lc.x > x then
- KOPALKA.rot(sides.back)
- while lc.x > x do
- KOPALKA.mForw(action,arg)
- end
- end
- if lc.x < x then
- KOPALKA.rot(sides.forward)
- while lc.x < x do
- KOPALKA.mForw(action,arg)
- end
- end
- if lc.z > z then
- KOPALKA.rot(sides.left)
- while lc.z > z do
- KOPALKA.mForw(action,arg)
- end
- end
- if lc.z < z then
- KOPALKA.rot(sides.right)
- while lc.z < z do
- KOPALKA.mForw(action,arg)
- end
- end
- while lc.y > y do
- KOPALKA.mDown(action,arg)
- end
- while lc.y < y do
- KOPALKA.mUp(action,arg)
- end
- end
- function KOPALKA.home(service, emergency)
- if (mode == BACK_TO_BASE) or (mode == EMERGENCY) then
- return
- end
- if emergency then
- mode = EMERGENCY
- KOPALKA.mTo(lc.x, 0, lc.z)
- else
- if mode == BACK_TO_MINE then
- printSt("Не могу добраться до точки возобновления работы. Вероятно карьер слишком большой")
- os.exit(1)
- end
- mode = BACK_TO_BASE
- end
- sendSt("Возвращаюсь на базу.")
- temp_state.x = lc.x
- temp_state.y = lc.y
- temp_state.z = lc.z
- temp_state.dr = lc.dr
- KOPALKA.mTo(0, 0, 0)
- KOPALKA.rot(2)
- KOPALKA.drop_scrap()
- KOPALKA.drop()
- --KOPALKA.rot(3)
- if service then
- service()
- end
- end
- function KOPALKA.back_to_mine(action, arg)
- printSt("Продолжаю работу.")
- mode = BACK_TO_MINE
- KOPALKA.mTo(0, temp_state.y, 0, action, arg)
- KOPALKA.mTo(temp_state.x, temp_state.y, temp_state.z, action, arg)
- KOPALKA.rot(temp_state.dr)
- temp_state.x = 0
- temp_state.y = 0
- temp_state.z = 0
- temp_state.dr = 3
- mode = MINE
- end
- -----------------------------------ДВИЖЕНИЕ С ПРОГРАММНОЙ НАВИГАЦИЕЙ [END]
- function KOPALKA.check_inv()
- return r.inventorySize()
- end
- function KOPALKA.inv_sorting()
- local items_stored = 0
- for i=1, inv_size-1 do
- if r.count(i) == 0 then
- for j=inv_size-1, 1, -1 do
- if r.count(j) > 0 then
- if j<i then
- break
- end
- r.select(j)
- r.transferTo(i)
- break
- end
- end
- end
- end
- for i=1,inv_size do
- if r.count(i) > 0 then
- items_stored = items_stored + 1
- end
- end
- r.select(1)
- return items_stored/inv_size
- end
- function KOPALKA.check_state(chkInventory, chkTool, chkEnergy)
- chkInventory = chkInventory or true
- chkTool = chkTool or true
- chkEnergy = chkEnergy or true
- --printSt(sprintf("Проверка состояния (время работы: %d)", computer.uptime()))
- local function inventory()
- local need_to_home = false
- if (r.count(inv_size-2) > 0) then
- if KOPALKA.drop_scrap() > 0.9 then
- need_to_home = true
- else
- need_to_home = false
- end
- end
- if need_to_home then
- sendSt("Инвентарь заполнен.")
- end
- return need_to_home
- end
- local function wayChargeService()
- local need_energy = computer.energy() < (computer.maxEnergy()*energyGenPercent/100)
- local need_to_home = computer.energy() < (computer.maxEnergy()*energyReturnPercent/100)
- if need_energy and comp.isAvailable("generator") and comp.generator.count() == 0 then
- local slt = KOPALKA.inv_scaner(fuel_list, true)
- if slt ~= 0 then
- r.select(slt)
- sendSt("Запускаю генератор.")
- comp.generator.insert()
- r.select(1)
- end
- end
- if need_to_home then
- sendSt("Недостаточно энергии.")
- end
- return need_to_home
- end
- local function chargeService()
- while computer.energy() < (computer.maxEnergy()*energyStartPercent/100) do
- printSt("Недостаточно энергии.")
- if comp.isAvailable("generator") and comp.generator.count() == 0 then
- local slt = KOPALKA.inv_scaner(fuel_list, false)
- if slt ~= 0 then
- r.select(inv_size-2)
- inv.suckFromSlot(3, slt)
- printSt("Запускаю генератор.")
- comp.generator.insert()
- r.select(1)
- end
- end
- os.sleep(15)
- end
- printSt("Аккумулятор заряжен.")
- end
- local function homeService()
- KOPALKA.charge_tool(charge_side, inv_size-2)
- chargeService()
- end
- if (chkInventory and inventory()) or (chkEnergy and wayChargeService()) or
- (chkTool and KOPALKA.charge_tool(charge_side, inv_size-2)) then
- KOPALKA.home(homeService)
- KOPALKA.back_to_mine()
- end
- end
- function KOPALKA.inv_scaner(filter, internal, start_slot) --автопоисковик заданного итема в своем инвентаре по системному имени. возвращает номер ячейки итема, первого найденного от начала ивентаря.
- ins = inv.getInventorySize(3)
- if start_slot == nil then
- start_slot = 1
- end
- if filter == "empty" then
- if internal then
- for i=start_slot, inv_size do
- if inv.getStackInInternalSlot(i) == nil then
- return i
- end
- end
- else
- for i=start_slot, inv.getInventorySize(3) do
- if inv.getStackInSlot(3, i) == nil then
- return i
- end
- end
- end
- end
- if internal then
- for i=start_slot, inv_size do
- if inv.getStackInInternalSlot(i) ~= nil then
- if pcall(pairs, filter) then
- for j, name in pairs(filter) do
- if inv.getStackInInternalSlot(i).name == name then
- return i
- end
- end
- else
- if inv.getStackInInternalSlot(i).name == filter then
- return i
- end
- end
- end
- end
- return 0
- else
- if ins ~= nil then
- for i=start_slot, ins do
- if inv.getStackInSlot(3, i) ~= nil then
- if pcall(pairs, filter) then
- for j, name in pairs(filter) do
- if inv.getStackInSlot(3, i).name == name then
- return i
- end
- end
- else
- if inv.getStackInSlot(3, i).name == filter then
- return i
- end
- end
- end
- end
- return 0
- else
- return 0
- end
- end
- end
- function KOPALKA.distance(blockA, blockB)
- local dist = math.sqrt(math.pow(blockA.x - blockB.x,2) +
- math.pow(blockA.z - blockB.z,2) + math.pow(blockA.y - blockB.y,2))
- return dist
- end
- function KOPALKA.closest_point(point, points)
- local cl_num = 1
- local length = KOPALKA.distance(point, points[1])
- for i=1, #points do
- local l = KOPALKA.distance(point, points[i])
- if l < length then
- cl_num = i
- length = l
- end
- end
- return cl_num
- end
- function KOPALKA.waypoints(ores_table, last)
- local yeildGuard = 0
- local way_table = {}
- local count = #ores_table
- table.insert(way_table, {x=lc.x, z=lc.z, y=lc.y})
- while count ~= #way_table - 1 do
- yeildGuard = yeildGuard + 1
- if yeildGuard == 100 then
- yeildGuard = 0
- pause()
- end
- local j = KOPALKA.closest_point(way_table[#way_table], ores_table)
- table.insert(way_table, ores_table[j])
- table.remove(ores_table, j)
- end
- return way_table, last
- end
- function KOPALKA.scanVolume(xn, zn, side, hiLayer, loLayer) --сканирование карьерного "этажа" заданного радиуса -10 блоков вниз+сканер+10 блоков вверх; bedrock - верхний уровень бедрока
- local geo = geolyzer
- local ores_table = {}
- local last = false
- local x_limit = 0
- local z_limit = 0
- local x_increment = 1
- local z_increment = 1
- if side == "north" or side == "север" then
- x_limit = zn
- x_increment = 1
- z_limit = -xn
- z_increment = -1
- elseif side == "west" or side == "запад" then
- x_limit = -xn
- x_increment = -1
- z_limit = -zn
- z_increment = -1
- elseif side == "south" or side == "юг" then
- x_limit = -zn
- x_increment = -1
- z_limit = xn
- z_increment = 1
- elseif side == "east" or side == "восток" or side == nil then
- x_limit = xn
- x_increment = 1
- z_limit = zn
- z_increment = 1
- end
- for xt=0,x_limit,x_increment do
- for zt=0,z_limit,z_increment do
- local scan = KOPALKA.scanPilar(xt, zt)
- for yt = hiLayer, loLayer, -1 do
- local y = lc.y + yt
- local hardness = scan[33 + yt]
- if hardness > minHardness and hardness < maxHardness and not (yt == 0 and zt == 0 and xt == 0) then
- if side == "north" or side == "север" then
- table.insert(ores_table, {x=math.abs(zt)+lc.x, z=math.abs(xt)+lc.z, y = y})
- elseif side == "west" or side == "запад" then
- table.insert(ores_table, {x=math.abs(xt)+lc.x, z=math.abs(zt)+lc.z, y = y})
- elseif side == "south" or side == "юг" then
- table.insert(ores_table, {x=math.abs(zt)+lc.x, z=math.abs(xt)+lc.z, y = y})
- elseif side == "east" or side == "восток" or side == nil then
- table.insert(ores_table, {x=math.abs(xt)+lc.x, z=math.abs(zt)+lc.z, y = y})
- end
- end
- end
- end
- end
- return ores_table
- end
- function KOPALKA.whatsSide()
- printSt("Ориентирование в пространстве.")
- local function isBlock(dens)
- if dens ~= nil and dens ~= 0 then
- return 1
- elseif dens == 0 then
- return 0
- end
- end
- local function check(fig, front)
- local figure1 = {
- east = isBlock(KOPALKA.scanPilar(1,0)[33]),
- south = isBlock(KOPALKA.scanPilar(0,1)[33]),
- west = isBlock(KOPALKA.scanPilar(-1,0)[33]),
- north = isBlock(KOPALKA.scanPilar(0,-1)[33])
- }
- if front then
- if fig.east > figure1.east then
- return "east"
- elseif fig.south > figure1.south then
- return "south"
- elseif fig.west > figure1.west then
- return "west"
- elseif fig.north > figure1.north then
- return "north"
- end
- elseif not front then
- if fig.east < figure1.east then
- return "east"
- elseif fig.south < figure1.south then
- return "south"
- elseif fig.west < figure1.west then
- return "west"
- elseif fig.north < figure1.north then
- return "north"
- end
- end
- end
- local figure = {
- east = isBlock(KOPALKA.scanPilar(1,0)[33]),
- south = isBlock(KOPALKA.scanPilar(0,1)[33]),
- west = isBlock(KOPALKA.scanPilar(-1,0)[33]),
- north = isBlock(KOPALKA.scanPilar(0,-1)[33])
- }
- KOPALKA.rot(3)
- while true do
- if r.detect() then
- r.swing()
- local direction = check(figure, true)
- r.place()
- return direction
- elseif r.detectDown() then
- r.swingDown()
- r.place()
- local direction = check(figure, false)
- r.swing()
- r.placeDown()
- return direction
- end
- printSt("Для ориентирования в пространстве недостаточно данных.")
- printSt("Пожалуйста установите любой блок перед или под роботом и повторите попытку")
- os.exit(1)
- end
- end
- function KOPALKA.scanPilar(x, z)
- local scan = geolyzer.scan(x, z, true)
- incActionCnt()
- return scan, bedrock
- end
- local testBedrock
- local flatBedrock
- function KOPALKA.findoutBedrockLevel()
- printSt("Проверка уровня бедрока. Вертикальная шахта до дна и обратно.")
- for i = lc.y, -worldHeight + 1, -scanRadius do
- local tempr = KOPALKA.scanPilar(0, 0)
- for i = 1, scanRadius do
- if tempr[33 - i] < -0.3 then
- local bedrockHi = lc.y - i
- if testBedrock then
- printSt("Бедрок обнаружен на уровне "..bedrockHi)
- end
- KOPALKA.mTo(lc.x, bedrockHi + 1, lc.z)
- local tempr = KOPALKA.scanPilar(0, 0)
- local bedrockLo = bedrockHi
- for i = 5, 1, -1 do
- if tempr[33 - i] < -0.3 then
- bedrockLo = lc.y - i
- if testBedrock then
- printSt("Нижний уровень бедрока "..bedrockLo)
- end
- break
- end
- end
- local scannedBedrockWidth = bedrockHi - bedrockLo + 1
- local bedrock
- if flatBedrock then
- bedrock = bedrockHi
- else
- bedrock = bedrockLo + (bedrockWidth - 1)
- end
- if testBedrock then
- printSt("Толщина бедрока в точке старта "..scannedBedrockWidth)
- printSt("Уровень бедрока установлен "..bedrock)
- end
- return bedrock
- end
- end
- KOPALKA.mTo(lc.x, i, lc.z)
- end
- printSt("Бедрок не обнаружен")
- os.exit(1)
- end
- function KOPALKA.quarry(quarryLength, quarryWidth, quarryHeight, side)
- if side == nil then
- side = sides.front
- end
- function dig(h)
- local try = 0
- if h >= 3 then
- KOPALKA.swingmove(sides.up, false)
- end
- if h >=2 then
- KOPALKA.swingmove(sides.down, false)
- end
- end
- if not quarryHeight then
- quarryHeight = 255
- end
- local doTurnRight = true
- for yy = 0, math.ceil(quarryHeight / 3) * 3 - 1, 3 do
- local h = quarryHeight - yy
- if yy > 0 then
- if h >= 3 then
- n = 3
- else
- n = 2
- end
- for n = n, 1, -1 do
- KOPALKA.mDown()
- end
- KOPALKA.turnAround()
- elseif h >= 3 then
- KOPALKA.mDown()
- end
- for zz = 1, quarryWidth do
- for xx = 1, quarryLength - 1 do
- KOPALKA.mForw(dig, h)
- end
- if zz < quarryWidth then
- if doTurnRight then
- KOPALKA.turnRight()
- else
- KOPALKA.turnLeft()
- end
- KOPALKA.mForw(dig, h)
- if doTurnRight then
- KOPALKA.turnRight()
- else
- KOPALKA.turnLeft()
- end
- doTurnRight = not doTurnRight
- end
- end
- dig(h)
- end
- KOPALKA.home()
- KOPALKA.rot(3)
- printSt("Всего блоков пройдено: "..way)
- printSt('Робот '..r.name()..' завершил работу.')
- end
- function KOPALKA.geoMiner(mineLength, mineWidth, mineHeight, side, clusterLength, clusterWidth)
- progress = { oreCount = 0 }
- if side == nil then
- side = KOPALKA.whatsSide()
- end
- mineHeight = mineHeight or -KOPALKA.findoutBedrockLevel()
- progress.mineLength = mineLength
- progress.mineWidth = mineWidth
- progress.mineHeight = mineHeight
- progress.numClusters = math.ceil(mineLength / clusterLength)
- * math.ceil(mineWidth / clusterWidth)
- * math.ceil(mineHeight / clusterHeight)
- progress.currentCluster = 0
- for x = 0, mineLength - 1, clusterLength do
- l = clusterLength
- if x + clusterLength > mineLength then
- l = mineLength - x
- end
- for z = 0, mineWidth - 1, clusterWidth do
- w = clusterWidth
- if z + clusterWidth > mineWidth then
- w = mineWidth - z
- end
- local bottomLayer = mineHeight - 1
- for y = scanRadius, math.ceil(mineHeight / clusterHeight) * clusterHeight, clusterHeight do
- local loLayer = -math.min(scanRadius, bottomLayer - y)
- local hiLayer = scanRadius
- if y >= mineHeight then
- hiLayer = 0
- loLayer = -math.min(scanRadius, scanRadius - (y - bottomLayer))
- y = mineHeight - mineHeight%clusterHeight
- end
- progress.currentCluster = progress.currentCluster + 1
- progress.clusterStartPoint = {x = x, y = -y, z = z}
- progress.clusterOreCount = 0
- progress.clusterNumOres = 0
- KOPALKA.clusterDigger(progress.clusterStartPoint, l, w, side, hiLayer, loLayer)
- end
- end
- end
- KOPALKA.home()
- KOPALKA.rot(3)
- printSt("Итого руды добыто: "..progress.oreCount)
- printSt("Всего блоков пройдено: "..way)
- printSt('Робот '..r.name()..' завершил работу.')
- end
- function KOPALKA.clusterDigger(start_point, l, w, side, hiLayer, loLayer)
- sendSt(sprintf("Кластер: (%d, %d) размером (%d, %d) на уровне %d (%d->%d)",
- start_point.x, start_point.z, l, w, start_point.y, loLayer, hiLayer))
- KOPALKA.mTo(start_point.x, start_point.y, start_point.z)
- sendSt("Сканирование...")
- local arr = KOPALKA.scanVolume(l-1, w-1, side, hiLayer, loLayer)
- progress.clusterNumOres = #arr
- if progress.clusterNumOres > 0 then
- sendSt("Найдено "..tostring(progress.clusterNumOres).." блока(ов)...")
- sendSt("Оптимизация пути...")
- arr = KOPALKA.waypoints(arr)
- sendSt("Добыча...")
- local n = #arr
- for i = 2, n do
- KOPALKA.mTo(arr[i].x, arr[i].y, arr[i].z)
- progress.clusterOreCount = progress.clusterOreCount + 1
- progress.oreCount = progress.oreCount + 1
- if (i % 10 == 1 or i == n) then
- sendSt(sprintf("%d из %d", progress.clusterOreCount, progress.clusterNumOres))
- end
- end
- end
- sendSt(sprintf("Кластер: (%d, %d) на уровне %d (%d->%d) обработан",
- start_point.x, start_point.z, start_point.y, loLayer, hiLayer))
- end
- function KOPALKA.check_components(ignoreCheck)
- ignoreCheck = ignoreCheck or { }
- local function stop()
- print('> ')
- if tonumber(io.read()) ~= 1 then
- os.exit()
- end
- end
- if comp.isAvailable("tunnel") then
- warp = true
- print("\t Связанная карта....доступна.")
- else
- print("\t Связанная карта не обнаружена. Начать работу? (0/1)")
- stop()
- end
- if comp.isAvailable("chunkloader") then
- comp.chunkloader.setActive(true)
- print("\t Чанклоадер....доступен.")
- else
- print("\t Чанклоадер не обнаружен, возможны проблемы и ошибки. Начать работу без чанклоадера? (0/1)")
- stop()
- end
- if comp.isAvailable("inventory_controller") then
- print("\t Контроллер инвентаря....доступен.")
- else
- print("\t Контроллер инвентаря не обнаружен, возможны проблемы и ошибки. Принудительная остановка программы.")
- os.exit()
- end
- if comp.isAvailable("generator") then
- print("\t Генератор....доступен.")
- else
- print("\t Генератор не обнаружен, возможны проблемы и ошибки. Начать работу без генератора? (0/1)")
- stop()
- end
- if comp.isAvailable("geolyzer") then
- print("\t Геосканер....доступен.")
- geolyzer = comp.geolyzer
- else
- if not ignoreCheck.geolyzer then
- print("\t Геосканер не обнаружен, возможны проблемы и ошибки. Принудительная остановка программы.")
- os.exit()
- end
- end
- if pcall(r.select,KOPALKA.inv_scaner("Forestry:scoop", true)) then
- r.transferTo(inv_size)
- r.select(1)
- print("\t Сачок....доступен.")
- else
- if not ignoreCheck.scoop then
- print("\t Сачок не обнаружен, возможны проблемы и ошибки. Начать работу без сачка?")
- stop()
- end
- end
- if r.durability() ~= nil then
- print("\t Инструмент....доступен.")
- else
- print("\t Инструмент не обнаружен, возможны проблемы и ошибки. Принудительная остановка программы.")
- os.exit()
- end
- print("\n Все компоненты в наличии.\n Программа может быть запущена.")
- end
- function KOPALKA.mine(x, z, mineHeight, side, x_lim, z_lim, quarry, ignoreCheck)
- if quarry then
- ignoreCheck = { geolyzer = true }
- end
- KOPALKA.check_components(ignoreCheck)
- lc.xMax = x
- lc.zMax = z
- way = 0
- term.clear()
- printSt("Старт карьера: "..x.."x"..z.." блоков.")
- local worker = KOPALKA.geoMiner
- if quarry then
- worker = KOPALKA.quarry
- end
- local ok, err = pcall(worker, x, z, mineHeight, side, x_lim, z_lim)
- if not ok then
- if type(err) ~= "table" then
- printSt(err)
- end
- printSt('Ошибка/препятствие. Возврат робота.')
- KOPALKA.home(nil, true)
- KOPALKA.rot(3)
- end
- end
- function main(tArgs, options)
- local function argNumber(x)
- local v = tonumber(x)
- if type(v) ~= 'number' then
- io.write("Аргументы должны быть заданы в виде чисел.\n")
- os.exit(1)
- end
- return v
- end
- local function getNumberOption(name)
- local v = options[name]
- if v then
- v = argNumber(v)
- end
- return v
- end
- if options.help then
- io.write("Установите робота в левом верхнем углу карьера. \n")
- io.write("За спиной робота — сундук. Слева — зарядник IC2/ \n")
- io.write("OC. Если размер_вниз не указан робот будет копать\n")
- io.write("до бедрока. В этом случае укажите ширину бедрока \n")
- io.write("опцией --bedrock-width. Или добавте опцию -f, ес-\n")
- io.write("ли бедрок плоский. Робот будет добывать блоки, \n")
- io.write("плотность которых находится в интервале (a, b). \n")
- io.write("a - мин. плотность, b - макс. плотность. \n")
- io.write("Опция --scan-radius устанавливает радиус сканиро-\n")
- io.write("вания по вертикали. Для ванильного конфига OC ре-\n")
- io.write("комендуется значение 5. Также можно указать его \n")
- io.write("в 11 строке программы. Опция --estart - заряд \n")
- io.write("акк.(%), необходимый для старта. При заряде акк. \n")
- io.write("ниже --egen - вкл. ген-р; --ereturn - возврат. \n")
- io.write("Для выкапывания карьера, укажите опцию --quarry \n")
- return
- end
- if #tArgs == 2 or #tArgs == 3 then
- bedrockWidth = getNumberOption("bedrock-width") or bedrockWidth
- minHardness = getNumberOption("min-hardness") or minHardness
- maxHardness = getNumberOption("max-hardness") or maxHardness
- scanRadius = getNumberOption("scan-radius") or scanRadius
- clusterHeight = scanRadius * 2 + 1
- local clusterSize = getNumberOption("cluster-size") or 32
- local bedrockWidth = getNumberOption("bedrock-width") or bedrockWidth
- testBedrock = options["test-bedrock"]
- flatBedrock = options["flat-bedrock"] or options.f
- local x = argNumber(tArgs[1])
- local z = argNumber(tArgs[2])
- local mineHeight = tArgs[3] and argNumber(tArgs[3])
- dont_drop_scrap = options["dont-drop-scrap"]
- KOPALKA.mine(x, z, mineHeight, nil, clusterSize, clusterSize, options.quarry or options.q)
- else
- io.write("Запуск:\nkopalka размер_вперёд размер_справа [размер_вниз]\n")
- io.write("Опции:\n")
- io.write("--help — информация о программе\n")
- io.write("--flat-bedrock, -f — если бедрок плоский \n")
- io.write(sprintf("--bedrock-width=<ширина слоя бедрока> [%d]\n", bedrockWidth))
- io.write(sprintf("--scan-radius=<радиус сканирования по верт.> [%d]\n", scanRadius))
- io.write(sprintf("--cluster-size=<размер кластера> [32]\n"))
- io.write(sprintf("--min-hardness=<мин. плотность> [%s]\n", minHardness))
- io.write(sprintf("--max-hardness=<макс. плотность> [%s]\n", maxHardness))
- io.write(sprintf("--estart=<уровень заряда для старта> [%s%%]\n", energyStartPercent))
- io.write(sprintf("--egen=<уровень заряда вкл. генератора> [%s%%]\n", energyGenPercent))
- io.write(sprintf("--ereturn=<уровень заряда для возврата> [%s%%]\n", energyReturnPercent))
- io.write("--quarry, -q — карьер\n")
- end
- end
- main(shell.parse(...))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement