Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Totoro GeoMiner Alpha 0.02 --
- local computer = require('computer')
- local robot = require('robot')
- local event = require('event')
- local com = require('component')
- -- Команды --
- STOP = 0x000000
- START = 0xFFFFFF
- COMEBACK = 0xC0FFEE
- BEACON = 0xBA0BAB
- -- Состояния --
- SCANNING = 0x000001
- MINING = 0x000002
- CHARGING = 0x000003
- WAITING = 0x000004
- DEADLOCK = 0x000005
- CONSTRUSTION = 0x000006
- -- Константы --
- BEGIN_ON_START = true
- START_DIR = 2 -- NORTH
- INVENTORY_SIZE = 32
- VALUABLE = 2.0
- PORT = 27
- LAYER_SIZE = 2
- LAYER_RAD = 32
- ATTEMPTS = 40
- MAX = 100
- --
- function trytofind(name)
- if com.isAvailable(name) then
- return com.getPrimary(name)
- else
- return nil
- end
- end
- local tunnel = trytofind('tunnel')
- local geo = trytofind('geolyzer')
- local gen = trytofind('generator')
- local modem = trytofind('modem')
- --======================================= Н А В И Г А Ц И Я ======================================--
- moves = 0
- loc = {x=0, y=0, z=0, d=START_DIR}
- function forward()
- if robot.forward() then
- if loc.d == 0 then loc.z = loc.z+1
- elseif loc.d == 1 then loc.x = loc.x-1
- elseif loc.d == 2 then loc.z = loc.z-1
- else loc.x = loc.x+1 end
- moves = moves + 1
- return true
- else
- return false
- end
- end
- function up()
- if robot.up() then
- loc.y = loc.y+1
- moves = moves + 1
- return true
- else
- return false
- end
- end
- function down()
- if robot.down() then
- loc.y = loc.y-1
- moves = moves + 1
- return true
- else
- return false
- end
- end
- function turnRight()
- loc.d = (loc.d+1)%4
- robot.turnRight()
- end
- function turnAround()
- loc.d = (loc.d+2)%4
- robot.turnAround()
- end
- function turnLeft()
- loc.d = (loc.d+3)%4
- robot.turnLeft()
- end
- --============================= Т О П Л И В О И И Н В Е Н Т А Р Ь =============================--
- function checkFuel()
- if gen ~= nil then
- if (computer.maxEnergy() - computer.energy()) > 1000 then
- if gen.count() < 64 then
- for i=1, INVENTORY_SIZE do
- robot.select(i)
- if gen.insert() then break end
- end
- end
- end
- end
- end
- --====================================== П О И С К Р У Д Ы ======================================--
- data = {}
- function setData(x, z, d)
- if data[x] == nil then data[x] = {} end
- data[x][z] = d
- end
- function setDataBlock(x, y, z, d)
- data[x][z][y+33] = d
- end
- function getData(x, z)
- if data[x] ~= nil then return data[x][z] end
- return nil
- end
- function updateData()
- for k, v in pairs(data) do
- -- обрезаем по координате X
- if math.abs(k - loc.x) > LAYER_RAD then
- data[k] = nil
- else
- for a, b in pairs(v) do
- -- обрезаем по координате Z
- if math.abs(a - loc.z) > LAYER_RAD then
- v[a] = nil
- end
- end
- end
- end
- end
- -- ищем самый плотный блок в колонне
- function check(x, z, y, ow, oy)
- if getData(x,z) == nil then return ow, oy end
- if getData(x,z)[y] > ow then return getData(x,z)[y], y end
- return ow, oy
- end
- function best(x, z)
- local worth = 0.0
- local wy = 0
- for y=33-LAYER_SIZE, 33+LAYER_SIZE do
- if x~=0 or z~=0 or y~=33 then
- worth, wy = check(x, z, y, worth, wy)
- end
- end
- return worth, wy
- end
- -- сканируем колонны по окружности
- function scan(dist)
- local value = 0
- local vx = 0
- local vy = 0
- local vz = 0
- for z=-dist, dist do
- x = dist - math.abs(z)
- if getData(x+loc.x, z+loc.z) == nil then
- while loc.y>0 do forcedown() end
- while loc.y<0 do forceup() end
- setData(x+loc.x, z+loc.z, geo.scan(x, z))
- end
- local w, y = best(x+loc.x, z+loc.z)
- if w >= value then
- value = w
- vx = x; vy = y; vz = z
- end
- if x ~= 0 then
- if getData(loc.x-x, z+loc.z) == nil then
- while loc.y>0 do forcedown() end
- while loc.y<0 do forceup() end
- setData(loc.x-x, z+loc.z, geo.scan(-x, z))
- end
- local w, y = best(loc.x-x, z+loc.z)
- if w >= value then
- value = w
- vx = -x; vy = y; vz = z
- end
- end
- end
- return value, vx, vy, vz
- end
- -- сканируем концентрическими окружностями
- function search()
- for distance=0, LAYER_RAD do
- print("Дистанция: "..distance)
- v, x, y, z = scan(distance)
- if v >= VALUABLE then
- return true, x+loc.x, y-33, z+loc.z, v
- end
- end
- return false
- end
- --======================================== Д В И Ж Е Н И Е ========================================--
- function turnTo(dir)
- while loc.d < dir do turnRight() end
- while loc.d > dir do turnLeft() end
- end
- function forceforward()
- local c = 0
- while not forward() do
- robot.swing()
- c = c+1
- if c > ATTEMPTS then return false end
- end
- return true
- end
- function forceup()
- local c = 0
- while not up() do
- robot.swingUp()
- c = c+1
- if c > ATTEMPTS then return false end
- end
- return true
- end
- function forcedown()
- local c = 0
- while not down() do
- robot.swingDown()
- c = c+1
- if c > ATTEMPTS then return false end
- end
- return true
- end
- function moveTo(target)
- if loc.x < target.x then
- turnTo(3)
- if forceforward() then return true end
- end
- if loc.x > target.x then
- turnTo(1)
- if forceforward() then return true end
- end
- if loc.z < target.z then
- turnTo(0)
- if forceforward() then return true end
- end
- if loc.z > target.z then
- turnTo(2)
- if forceforward() then return true end
- end
- if loc.y < target.y then
- if forceup() then return true end
- end
- if loc.y > target.y then
- if forcedown() then return true end
- end
- return false
- end
- --======================================= С О С Т О Я Н И Я =======================================--
- function setState(code)
- if tunnel ~= nil then tunnel.send(code) end
- if modem ~= nil then modem.broadcast(PORT, code) end
- if code == DEADLOCK then
- active = false
- end
- end
- --==================================== Г Л А В Н Ы Й Ц И К Л ====================================--
- -- в конструкции должен присутствовать геосканер
- if geo == nil then
- setState(CONSTRUSTION)
- return false
- end
- if modem ~= nil then modem.open(PORT) end
- print("Ожидаю сигнала...")
- active = BEGIN_ON_START
- target = {x=0, y=0, z=0, active=false, worth=0}
- while true do
- checkFuel()
- -- обработка команд
- name, add, _, _, _, message, a,b,c = event.pull(0.1)
- if name == 'modem_message' then
- if message == STOP then
- active = false
- elseif message == START then
- active = true
- end
- end
- -- поиск руды и добыча
- if active then
- -- если цель не обнаружена - сканировать
- if not target.active then
- setState(SCANNING)
- target.active, target.x, target.y, target.z, target.worth = search()
- print('Новая цель: ', target.x, target.y, target.z, target.worth)
- -- если есть цель - двигаться к цели
- else
- setState(MINING)
- -- робот двигается блоками по 10
- for i=1, 10 do
- -- если движение прекратилось
- if not moveTo(target) then
- target.active = false
- -- если робот не дошел до цели
- if target.x ~= loc.x or target.y ~= loc.y or target.z ~= loc.z then
- setState(DEADLOCK)
- else
- setDataBlock(loc.x, loc.y, loc.z, 0.0)
- updateData()
- end
- break
- end
- end
- end
- end
- end
- if modem ~= nil then modem.close(PORT) end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement