Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- pastebin get erdG4yc0 quarry2
- --------------------------Константы----------------------------------------
- -- Высота слоя
- local layerHeight = 3
- local state_start = 0 -- инициализция
- local state_mining = 1 -- копаем ресусы
- local state_goto = 2 -- идем домой или обратно копать
- local state_home = 4 -- мы дома, разгружаемся и заправляемся
- local state_bedrock = 5 -- натолкнулись на бедрок, пытаемся выбраться
- --------------------------Конец объявления констант------------------------
- --------------------------Константные параметры----------------------------
- -- Размеры карьера
- local width, lenght, height = 5, 5, 256
- -- Куда будет черепаха копать, вправо или влево
- local reflection = 0; -- 1 влево
- -- Начальная позиция черепахи
- local startPos = vector.new((width - 1) * reflection, 0, 0)
- --------------------------Конец константных параметров----------------------------
- --------------------------Динамические параметры----------------------------------
- -- Позиция черепахи
- -- x - ширина; y - длина; z - глубина;
- local pos = vector.new(startPos.x, startPos.y, startPos.z)
- -- Текущее направление черепахи
- -- x = -1 | x = 1 | y = -1 | y = 1
- -- z - не используется
- local currDir = vector.new(0, 1, 0)
- -- Заданное направление
- -- Черепаха должна переместиться таким образом,
- -- что бы текущее направление соответствовало заданному
- -- x = [-1, 1]; y = [-1, 1]; z = [-1, 1]
- -- y = 1 - мы должны ехать вперед,
- -- y = -1 - мы должны ехать назад
- -- x = 1 - мы должны повернуть направо
- -- x = -1 - мы должны повернуть налево
- -- z = 1 - мы должны ехать вверх
- -- z = -1 - мы должны ехать вниз
- local givenDir = vector.new(1- reflection * 2, 1, -1)
- -- Когда выходим из состояния добычи, нужно сохранить позицию
- local posTmpMining = vector.new(0, 0, 0)
- local currDirTmpMining = vector.new(0, 0, 0)
- -- Куда мы хотим ехать когда используем goto
- local dirMining = 0
- -- Количество блоков на которое должна передвинуться черепаха
- -- относительно заданного направления
- local distantion = vector.new(0, lenght - 1, 0)
- -- Что мы делаем на данный момент
- local state = state_start
- -- Завершили ли мы добычу ресурсов
- local miningEnd = 0
- --------------------------Конец динамических параметров----------------------------
- --------------------------Копия динамических параметров----------------------------
- local clone_pos = vector.new(0, 0, 0)
- local clone_currDir = vector.new(0, 0, 0)
- local clone_givenDir = vector.new(0, 0, 0)
- local clone_distantion = vector.new(0, 0, 0)
- --------------------------Конец копии динамических параметров----------------------
- -- Скопировать текущее состояние в доп. память
- local function cloneState()
- clone_pos.x = pos.x
- clone_pos.y = pos.y
- clone_pos.z = pos.z
- clone_currDir.x = currDir.x
- clone_currDir.y = currDir.y
- clone_currDir.z = currDir.z
- clone_givenDir.x = givenDir.x
- clone_givenDir.y = givenDir.y
- clone_givenDir.z = givenDir.z
- clone_distantion.x = distantion.x
- clone_distantion.y = distantion.y
- clone_distantion.z = distantion.z
- end
- -- Восстановить текущее состояние из доп. памяти
- local function restoreState()
- pos.x = clone_pos.x
- pos.y = clone_pos.y
- pos.z = clone_pos.z
- currDir.x = clone_currDir.x
- currDir.y = clone_currDir.y
- currDir.z = clone_currDir.z
- givenDir.x = clone_givenDir.x
- givenDir.y = clone_givenDir.y
- givenDir.z = clone_givenDir.z
- distantion.x = clone_distantion.x
- distantion.y = clone_distantion.y
- distantion.z = clone_distantion.z
- end
- -- curr == true сохраняем текущее состояние
- -- curr == false сохраняем клонированное состояние
- local function saveState(curr)
- name = shell.getRunningProgram()
- local file = fs.open(name..".save","w")
- file.writeLine(width)
- file.writeLine(lenght)
- file.writeLine(height)
- file.writeLine(reflection)
- file.writeLine(startPos.x)
- file.writeLine(startPos.y)
- file.writeLine(startPos.z)
- file.writeLine(state)
- file.writeLine(miningEnd)
- file.writeLine(posTmpMining.x)
- file.writeLine(posTmpMining.y)
- file.writeLine(posTmpMining.z)
- file.writeLine(currDirTmpMining.x)
- file.writeLine(currDirTmpMining.y)
- file.writeLine(currDirTmpMining.z)
- file.writeLine(dirMining)
- if curr == true then
- file.writeLine(pos.x)
- file.writeLine(pos.y)
- file.writeLine(pos.z)
- file.writeLine(currDir.x)
- file.writeLine(currDir.y)
- file.writeLine(currDir.z)
- file.writeLine(givenDir.x)
- file.writeLine(givenDir.y)
- file.writeLine(givenDir.z)
- file.writeLine(distantion.x)
- file.writeLine(distantion.y)
- file.writeLine(distantion.z)
- else
- file.writeLine(clone_pos.x)
- file.writeLine(clone_pos.y)
- file.writeLine(clone_pos.z)
- file.writeLine(clone_currDir.x)
- file.writeLine(clone_currDir.y)
- file.writeLine(clone_currDir.z)
- file.writeLine(clone_givenDir.x)
- file.writeLine(clone_givenDir.y)
- file.writeLine(clone_givenDir.z)
- file.writeLine(clone_distantion.x)
- file.writeLine(clone_distantion.y)
- file.writeLine(clone_distantion.z)
- end
- file.close()
- end
- local function readState()
- name = shell.getRunningProgram()
- if not fs.exists(name..".save") then
- return false
- end
- local file = fs.open(name..".save","r")
- width = tonumber(file.readLine())
- lenght = tonumber(file.readLine())
- height = tonumber(file.readLine())
- reflection = tonumber(file.readLine())
- startPos.x = tonumber(file.readLine())
- startPos.y = tonumber(file.readLine())
- startPos.z = tonumber(file.readLine())
- state = tonumber(file.readLine())
- miningEnd = tonumber(file.readLine())
- posTmpMining.x = tonumber(file.readLine())
- posTmpMining.y = tonumber(file.readLine())
- posTmpMining.z = tonumber(file.readLine())
- currDirTmpMining.x = tonumber(file.readLine())
- currDirTmpMining.y = tonumber(file.readLine())
- currDirTmpMining.z = tonumber(file.readLine())
- dirMining = tonumber(file.readLine())
- pos.x = tonumber(file.readLine())
- pos.y = tonumber(file.readLine())
- pos.z = tonumber(file.readLine())
- currDir.x = tonumber(file.readLine())
- currDir.y = tonumber(file.readLine())
- currDir.z = tonumber(file.readLine())
- givenDir.x = tonumber(file.readLine())
- givenDir.y = tonumber(file.readLine())
- givenDir.z = tonumber(file.readLine())
- distantion.x = tonumber(file.readLine())
- distantion.y = tonumber(file.readLine())
- distantion.z = tonumber(file.readLine())
- file.close()
- return true
- end
- local function setStartup()
- if fs.exists("startup") then
- -- if fs.exists("startup.old") then
- fs.delete("startup")
- -- else
- -- shell.run("move","startup","startup.old")
- -- end
- end
- name = shell.getRunningProgram()
- local file = fs.open("startup","w")
- file.writeLine("shell.run(\""..name.."\")")
- file.close()
- end
- local function delStartup()
- if fs.exists("startup") then
- fs.delete("startup")
- end
- -- if fs.exists("startup.old") then
- -- shell.run("move","startup.old","startup")
- -- end
- name = shell.getRunningProgram()
- if fs.exists(name..".save") then
- fs.delete(name..".save")
- end
- end
- -- зеркально отразить вектор по оси
- -- x [0, 1]; y [0, 1]
- function Reflect(vec, x, y)
- vx = vec.x
- vy = vec.y
- if x == 1 then
- vx = -vec.x
- end
- if y == 1 then
- vy = -vec.y
- end
- return vector.new(vx, vy, vec.z)
- end
- local function inventoryFull()
- for i = 1, 16 do
- if turtle.getItemCount(i) <= 0 then
- return false
- end
- end
- return true
- end
- local function unload()
- print( "Unloading items..." )
- local n = 1
- if not turtle.detect() then
- print("no detect chest")
- while not turtle.detect() do
- os.sleep(1)
- end
- end
- while n <= 16 do
- turtle.select(n)
- if turtle.getItemCount(n) > 0 and not turtle.drop() then
- print("Don't unload to chest")
- os.sleep(5)
- else
- n = n + 1
- end
- end
- turtle.select(1)
- end
- -- Сколько нужно заправить топлива, что бы доехать
- -- dir - true; едем на базу
- -- dir - false; едем копать
- function countFillFuel(dir)
- local fuelLevel = turtle.getFuelLevel()
- local needed = 0
- if dir == true then
- -- сколько нужно что б доехать до базы
- needed = math.abs(startPos.x - pos.x) +
- math.abs(startPos.y - pos.y) +
- math.abs(pos.z - startPos.z) + 3
- else
- -- сколько нужно что б доехать до рабочего места и вернуться
- needed = math.abs(startPos.x - posTmpMining.x) +
- math.abs(startPos.y - posTmpMining.y) +
- math.abs(posTmpMining.z - startPos.z) + 3
- needed = needed * 2
- end
- if fuelLevel < needed then
- return needed - fuelLevel
- else
- return 0
- end
- end
- -- Смогли ли мы заправиться на месте?
- function refuelHere()
- -- Заправляемся
- if countFillFuel(true) > 0 then
- for i = 1, 16 do
- if turtle.getItemCount(i) > 0 then
- turtle.select(i)
- if turtle.refuel(64) then
- if countFillFuel(true) <= 0 then
- turtle.select(1)
- return true
- end
- end
- end
- end
- turtle.select(1)
- return false
- else
- return true
- end
- end
- function refuel()
- if countFillFuel(false) <= 0 then
- return
- end
- print("waiting for fuel")
- while countFillFuel(false) > 0 do
- for i = 1, 16 do
- if turtle.getItemCount(i) > 0 then
- turtle.select(i)
- turtle.refuel(64)
- end
- end
- sleep(1)
- end
- end
- local function down()
- while true do
- if turtle.detectDown() then
- if turtle.digDown() then
- -- print("detect block")
- else
- -- Мы не сможем переместиться
- -- Восстановим прошлое состояние
- restoreState()
- print("detect bedrock or unbreaking block")
- return false
- end
- elseif turtle.attackDown() then
- print("detect monster or player")
- else
- -- Сохраним текущее состояние
- saveState(true)
- if turtle.down() then
- -- print("it's ok!")
- -- checkBorder()
- return true
- else
- -- Мы не смогли переместиться
- -- Сохраним восстановим прошлое состояние
- saveState(false)
- if turtle.getFuelLevel() <= 0 then
- -- Что то пошло не так, у нас резко закончилось топливо
- print("ran out of fuel")
- refuelHere()
- else
- print("detect unknowing object")
- end
- os.sleep(0.5)
- end
- end
- end
- end
- local function up()
- while true do
- if turtle.detectUp() then --обнаружен блок, сломать
- if turtle.digUp() then
- -- print("detect block")
- else
- -- Мы не сможем переместиться
- -- Восстановим прошлое состояние
- restoreState()
- print("detect bedrock or unbreaking block")
- return false
- end
- elseif turtle.attackUp() then -- Сверху нет блока, проверяем есть ли там существо
- print("detect monster or player")
- else -- Передвигаемся вверх
- -- Сохраним текущее состояние
- saveState(true)
- if turtle.up() then
- -- it's ok!
- -- print("it's ok!")
- -- checkBorder()
- return true
- else
- -- Мы не смогли переместиться
- -- Сохраним восстановим прошлое состояние
- saveState(false)
- if turtle.getFuelLevel() <= 0 then
- -- Что то пошло не так, у нас резко закончилось топливо
- print("ran out of fuel")
- refuelHere()
- else
- print("detect unknowing object")
- end
- os.sleep(0.5)
- end
- end
- end
- end
- local function forward(mined)
- if mined then
- if turtle.detectUp() then
- turtle.digUp()
- --if inventoryFull() then
- -- returnSupplies()
- --end
- end
- if turtle.detectDown() then
- turtle.digDown()
- --if inventoryFull() then
- -- returnSupplies()
- --end
- end
- end
- while true do
- if turtle.detect() then -- обнаружен блок, сломать
- if turtle.dig() then
- -- print("detect block")
- --if mined and inventoryFull() then
- -- returnSupplies()
- --end
- else
- -- Мы не сможем переместиться
- -- Восстановим прошлое состояние
- restoreState()
- print("detect bedrock or unbreaking block")
- return false
- end
- elseif turtle.attack() then -- Впереди нет блока, проверяем есть ли там существо
- print("detect monster or player")
- --if mined and inventoryFull() then
- -- returnSupplies()
- --end
- else -- Передвигаемся вперед
- if mined then -- Уберем гравий и любые падающие блоки над головой
- while turtle.detectUp() do
- turtle.digUp()
- os.sleep(0.5)
- end
- end
- -- Сохраним текущее состояние
- saveState(true)
- if turtle.forward() then
- -- print("it's ok!")
- --checkBorder()
- return true
- else
- -- Мы не смогли переместиться
- -- Сохраним восстановим прошлое состояние
- saveState(false)
- if not turtle.detect() then
- if turtle.getFuelLevel() <= 0 then
- -- Что то пошло не так, у нас резко закончилось топливо
- print("ran out of fuel")
- refuelHere()
- else
- print("detect unknowing object")
- end
- end
- os.sleep(0.5)
- end
- end
- end
- end
- -- если dir - true, едем домой
- -- если dir - false, едем копать
- function startGoTo(dir)
- if dir == true then
- posTmpMining.x = pos.x
- posTmpMining.y = pos.y
- posTmpMining.z = pos.z
- currDirTmpMining.x = currDir.x
- currDirTmpMining.y = currDir.y
- currDirTmpMining.z = currDir.z
- dirMining = 1
- else
- dirMining = 0
- end
- state = state_goto
- saveState(true)
- end
- local tPosGT = vector.new(0, 0, 0)
- local tDirGT = vector.new(0, 0, 0)
- function GoTo()
- if dirMining == 1 then
- tPosGT.x = startPos.x
- tPosGT.y = startPos.y
- tPosGT.z = startPos.z
- else
- tPosGT.x = posTmpMining.x
- tPosGT.y = posTmpMining.y
- tPosGT.z = posTmpMining.z
- end
- -- идем по оси z
- if pos.z ~= tPosGT.z then
- if pos.z < tPosGT.z then
- -- идем вверх
- cloneState()
- pos.z = pos.z + 1
- up()
- else
- -- идем вниз
- cloneState()
- pos.z = pos.z - 1
- down()
- end
- return
- end
- -- ориентируемся и идем по x
- if pos.x ~= tPosGT.x then
- local d = 1 -- нам надо ехать вправо
- if pos.x > tPosGT.x then -- нет, все таки влево
- d = -1
- end
- -- нам нужно повернуться на 90
- if currDir.x == 0 then
- if d == currDir.y then
- currDir.x = d
- currDir.y = 0
- saveState(true)
- turtle.turnRight()
- else
- currDir.x = d
- currDir.y = 0
- saveState(true)
- turtle.turnLeft()
- end
- -- нам надо повернуться на 180
- elseif currDir.x ~= d then
- currDir.x = 0
- currDir.y = d
- saveState(true)
- turtle.turnRight()
- -- мы сориентировались. пошли вперед
- else
- cloneState()
- pos.x = pos.x + d
- forward(false)
- end
- return
- end
- -- ориентируемся и идем по y
- if pos.y ~= tPosGT.y then
- local d = 1 -- нам надо ехать вперед
- if pos.y > tPosGT.y then -- нет, все таки назад
- d = -1
- end
- -- нам нужно повернуться на 90
- if currDir.y == 0 then
- if d ~= currDir.x then
- currDir.y = d
- currDir.x = 0
- saveState(true)
- turtle.turnRight()
- else
- currDir.y = d
- currDir.x = 0
- saveState(true)
- turtle.turnLeft()
- end
- -- нам надо повернуться на 180
- elseif currDir.y ~= d then
- currDir.y = 0
- currDir.x = d
- saveState(true)
- turtle.turnLeft()
- -- мы сориентировались. пошли вперед
- else
- cloneState()
- pos.y = pos.y + d
- forward(false)
- end
- return
- end
- if dirMining == 1 then
- tDirGT.x = 0
- tDirGT.y = -1
- tDirGT.z = 0
- else
- tDirGT.x = currDirTmpMining.x
- tDirGT.y = currDirTmpMining.y
- tDirGT.z = currDirTmpMining.z
- end
- -- мы находимся в конечной позиции
- -- возможно нужно развернуться
- -- нам нужно повернуться на 180
- if currDir.x == tDirGT.x and currDir.y == tDirGT.y then
- -- Мы приехали
- if dirMining == 1 then
- state = state_home
- saveState(true)
- else
- state = state_mining
- saveState(true)
- end
- return
- elseif (currDir.x == 0 and tDirGT.x == 0) or
- (currDir.y == 0 and tDirGT.y == 0)
- then
- if currDir.x ~= 0 then
- currDir.y = -currDir.x
- currDir.x = 0
- saveState(true)
- turtle.turnRight()
- else
- currDir.x = currDir.y
- currDir.y = 0
- saveState(true)
- turtle.turnRight()
- end
- -- нам надо повернуться на 90
- elseif currDir.y == 0 then
- if currDir.x == tDirGT.y then
- currDir.y = tDirGT.y
- currDir.x = 0
- saveState(true)
- turtle.turnLeft()
- else
- currDir.y = tDirGT.y
- currDir.x = 0
- saveState(true)
- turtle.turnRight()
- end
- elseif currDir.x == 0 then
- if currDir.y == tDirGT.x then
- currDir.x = tDirGT.x
- currDir.y = 0
- saveState(true)
- turtle.turnRight()
- else
- currDir.x = tDirGT.x
- currDir.y = 0
- saveState(true)
- turtle.turnLeft()
- end
- end
- end
- function Minning()
- -- Нужно ли нам заправляться?
- if not refuelHere() then
- -- Надо съездить на базу
- startGoTo(true)
- return
- end
- -- Нужно ли нам выгрузить ресурсы?
- if inventoryFull() then
- -- Надо съездить на базу
- startGoTo(true)
- return
- end
- -- мы должны развернуться на 180
- if currDir.y ~= givenDir.y and currDir.x == 0 then
- -- Мы должны попытаться проехать по ширине карьера
- if distantion.x == 1 then
- -- Поворачиваем, после поворота мы будем стоять параллельно оси x
- -- тут магическое условие которое я скоро забуду и не пойму почему так работает :))
- -- на самом деле направление поворота зависит от направления движения
- -- если мы хотим повернуть черепаху направо то направление движения должно
- -- совпадать (численно) с желаемым направлением поворота
- -- -1 == -1; 1 == 1; поворот направо
- -- -1 ~= 1; 1 ~= -1; поворот налево
- -- 180 -> 90
- if givenDir.x == currDir.y then
- -- скорректируем наше текущее положение
- currDir.x = givenDir.x
- currDir.y = 0
- saveState(true)
- turtle.turnRight()
- -- 180 -> 90
- else
- -- скорректируем наше текущее положение
- currDir.x = givenDir.x
- currDir.y = 0
- saveState(true)
- turtle.turnLeft()
- end
- end
- -- сейчас мы стоим параллельно оси х
- -- мы должны развернуться на 90%
- elseif currDir.x ~= 0 then
- -- Двигаемся вбок на 1 блок если это нужно
- if distantion.x == 1 then
- -- Мы хотим передвинуться вперед, но уперлись в стенку
- -- Мы оказались в углу
- if (pos.x == 0 and currDir.x == -1) or
- (pos.x == width - 1 and currDir.x == 1)
- then
- -- Ехать в бок не будем
- -- Нужно поехать вниз
- givenDir.z = -1
- distantion.x = 0
- distantion.z = layerHeight
- givenDir = Reflect(givenDir, 1, 0)
- -- save
- return
- end
- -- Запоминаем текущее состояние на случай отката
- cloneState()
- -- Копаем и двигаемся вперед
- distantion.x = 0
- pos.x = pos.x + givenDir.x
- -- Мы наткнулись на бедрок спереди
- -- Возможно он есть над нами, пытаемся объехать его
- if not forward(true) then
- --distantion.x = 0
- --distantion.y = 0
- state = state_bedrock
- miningEnd = 1
- saveState(true)
- return
- end
- -- Если нам нужно ехать вниз, значит мы в углу
- -- Поехали вниз
- elseif distantion.z > 0 then
- -- Запоминаем текущее состояние на случай отката
- cloneState()
- pos.z = pos.z + givenDir.z
- -- Мы достигли дна
- if pos.z <= -(height) then
- restoreState()
- -- Поехали домой, работа закончена
- miningEnd = 1
- startGoTo(true)
- -- Едем домой
- return
- end
- -- Мы только начали опускаться
- if distantion.z == layerHeight then
- -- и стоим на предпоследнем слое
- -- Значит пора ехать домой
- if pos.z <= -(height - 1) then
- restoreState()
- -- Поехали домой, работа закончена
- miningEnd = 1
- startGoTo(true)
- return
- end
- else
- -- мы еще не проехались по этому слою
- if pos.z <= -(height - 1) then
- restoreState()
- distantion.z = 0
- return
- end
- end
- distantion.z = distantion.z - 1
- if givenDir.z == -1 then
- -- Пытаемся спуститься
- if not down() then
- -- Мы наехали на бедрок
- if distantion.z == layerHeight then
- -- Поехали домой, работа закончена
- miningEnd = 1
- startGoTo(true)
- return
- else
- distantion.z = 0
- end
- end
- --else
- -- up()
- end
- -- Нам не нужно никуда ехать. Разворачиваемся.
- -- См комментарий про поворот выше
- else
- if givenDir.y == currDir.x then
- -- скорректируем наше текущее положение
- currDir.x = 0
- currDir.y = givenDir.y
- saveState(true)
- turtle.turnLeft()
- else
- -- скорректируем наше текущее положение
- currDir.x = 0
- currDir.y = givenDir.y
- saveState(true)
- turtle.turnRight()
- end
- end
- return --?
- end
- -- Двигаемся по длине карьера
- if currDir.y == givenDir.y then
- -- Мы дошли до стенки, нужно развернуться
- if distantion.y == 0 then
- givenDir = Reflect(givenDir, 0, 1)
- distantion.x = 1
- distantion.y = lenght - 1
- -- save
- return
- else
- -- Запоминаем текущее состояние на случай отката
- cloneState()
- -- Копаем и двигаемся вперед
- pos.y = pos.y + givenDir.y
- distantion.y = distantion.y - 1
- -- Мы наткнулись на бедрок спереди
- -- Возможно он есть над нами, пытаемся объехать его
- if not forward(true) then
- --distantion.x = 0
- --distantion.y = 0
- state = state_bedrock
- miningEnd = 1
- saveState(true)
- return
- end
- end
- end
- end
- -- Мы дома
- -- Выгружаем ресурсы и заправляемся если нужно
- function Home()
- unload()
- if miningEnd == 1 then
- return false
- end
- refuel()
- startGoTo(false)
- return true
- end
- local tArgs = { ... }
- if #tArgs == 0 then
- print( "Recovering...")
- readState()
- elseif #tArgs == 2 then
- lenght = tonumber( tArgs[1] )
- width = tonumber( tArgs[2] )
- startPos.x = (width - 1) * reflection
- startPos.y = 0
- startPos.z = 0
- pos.x = startPos.x
- pos.y = startPos.y
- pos.z = startPos.z
- givenDir.x = 1- reflection * 2
- givenDir.y = 1
- givenDir.z = -1
- distantion.x = 0
- distantion.y = lenght - 1
- distantion.z = 0
- --setStartup()
- cloneState()
- pos.z = pos.z - 1
- down()
- state = state_mining
- miningEnd = 0
- end
- while true do
- if state == state_mining then
- Minning()
- elseif state == state_goto then
- GoTo()
- elseif state == state_home then
- if not Home() then
- print("is completed")
- break
- end
- else
- print("error state")
- break
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement