ComST 15 Опубликовано: 5 декабря, 2015 (изменено) Здравствуйте, друзья мои! Написал я тут намедни программу "Фермер". Классический вариант начинающего программиста: вскопал, посадил, собрал, посадил заново. Но мне показалось этого мало. Решил доработать надфилем, что бы робот был полностью самостоятельным. На данный момент робот делает следующее: удаляет лишние блоки земли и травы, взрыхляет почву (размер поля задается в программе), сажает семена, проверяет выросла ли пшеница, срубает выросшую, сажает заново, гоняет мобов с поля. Всё бы хорошо, но вот с последним пунктом у меня проблема. Для большей ясности приведу код: local r = require("robot") local component = require("component") local g = component.geolyzer local size = 5 -- размер квадратного поля function harvest() -- проверка блока снизу, взрыхление, сбор и посадка саженцев if g.analyze(0).name == "minecraft:wheat" then -- если внизу пшеница... if g.analyze(0).metadata == 7 then -- если пшеница выросла (metadata=7)... r.swingDown() -- срубаем пшеницу. (ПКМ) r.placeDown() -- посадить семена под сабой end else r.swingDown() r.useDown() -- взрыхлить почву под собой (ЛКМ) r.placeDown() -- посадить семена под сабой end end function forward() -- проверка блока впереди и движение вперед local _, det = r.detect() while det =="entity" do -- если впереди "сущность"... print("живой") -- печатает "Живой" r.swing() -- бьет его, чтобы убежал с поля end if det == "solid" then -- если впереди твердый блок... print("Блок") r.swing() -- уничтожить блок вперди else print("воздух") -- Впереди воздух end r.forward() -- движение вперед на 1 блок end function move() -- челночное движение робота по полю for y=1, size do -- движение по ширине от первого ряда до последнего harvest() for x=1, (size-1) do -- движение по длине от первого блока до последнего forward() -- движение вперед на 1 блок harvest() end if y < size then if y%2 == 1 then -- если ряд не четный... r.turnLeft() -- поворот влево forward() -- движение вперед r.turnLeft() -- поворот влево else r.turnRight() -- поворот вправо forward() -- движение вперед r.turnRight() -- поворот вправо end else r.turnAround() end end end r.up() r.forward() move() r.back() r.down() У меня проблема с циклом while do end. Робот себе спокойно копает, я встаю у него спереди. Соответственно он начинает меня бить тяпкой, до тех пор, пока не убьет или я не отвалю с пути. Когда я отхожу в сторону, робот не выходит из цикла. Я уже себе голову сломал почему. Есть подозрение, что блок перед роботом не обновляется. Но это уже крайность. Кто что может подсказать? Заранее спасибо! Изменено 5 декабря, 2015 пользователем ComST 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Fingercomp 4 409 Опубликовано: 5 декабря, 2015 (изменено) Здравствуйте, друзья мои! Написал я тут намедни программу "Фермер". Классический вариант начинающего программиста: вскопал, посадил, собрал, посадил заново. Но мне показалось этого мало. Решил доработать надфилем, что бы робот был полностью самостоятельным. На данный момент робот делает следующее: удаляет лишние блоки земли и травы, взрыхляет почву (размер поля задается в программе), сажает семена, проверяет выросла ли пшеница, срубает выросшую, сажает заново, гоняет мобов с поля. Всё бы хорошо, но вот с последним пунктом у меня проблема. Для большей ясности приведу код: local r = require("robot") local component = require("component") local g = component.geolyzer local size = 5 -- размер квадратного поля function harvest() -- проверка блока снизу, взрыхление, сбор и посадка саженцев if g.analyze(0).name == "minecraft:wheat" then -- если внизу пшеница... if g.analyze(0).metadata == 7 then -- если пшеница выросла (metadata=7)... r.swingDown() -- срубаем пшеницу. (ПКМ) r.placeDown() -- посадить семена под сабой end else r.swingDown() r.useDown() -- взрыхлить почву под собой (ЛКМ) r.placeDown() -- посадить семена под сабой end end function forward() -- проверка блока впереди и движение вперед local _, det = r.detect() while det =="entity" do -- если впереди "сущность"... print("живой") -- печатает "Живой" r.swing() -- бьет его, чтобы убежал с поля end if det == "solid" then -- если впереди твердый блок... print("Блок") r.swing() -- уничтожить блок вперди else print("воздух") -- Впереди воздух end r.forward() -- движение вперед на 1 блок end function move() -- челночное движение робота по полю for y=1, size do -- движение по ширине от первого ряда до последнего harvest() for x=1, (size-1) do -- движение по длине от первого блока до последнего forward() -- движение вперед на 1 блок harvest() end if y < size then if y%2 == 1 then -- если ряд не четный... r.turnLeft() -- поворот влево forward() -- движение вперед r.turnLeft() -- поворот влево else r.turnRight() -- поворот вправо forward() -- движение вперед r.turnRight() -- поворот вправо end else r.turnAround() end end end r.up() r.forward() move() r.back() r.down() У меня проблема с циклом while do end. Робот себе спокойно копает, я встаю у него спереди. Соответственно он начинает меня бить тяпкой, до тех пор, пока не убьет или я не отвалю с пути. Когда я отхожу в сторону, робот не выходит из цикла. Я уже себе голову сломал почему. Есть подозрение, что блок перед роботом не обновляется. Но это уже крайность. Кто что может подсказать? Заранее спасибо! Ты проверяй на наличие сущности в цикле самом Один раз он сохранил значение — и начинает шприть его. Вот тебе код. function forward() -- проверка блока впереди и движение вперед repeat local smth_ahead, det = r.detect() if det =="entity" then -- если впереди "сущность"... print("живой") -- печатает "Живой" r.swing() -- бьет его, чтобы убежал с поля elseif det == "solid" then -- если впереди твердый блок... print("Блок") r.swing() -- уничтожить блок вперди else print("воздух") -- Впереди воздух break -- на всякий случай end until not smth_ahead r.forward() -- движение вперед на 1 блок end Изменено 5 декабря, 2015 пользователем Fingercomp 4 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ComST Автор темы 15 Опубликовано: 5 декабря, 2015 Чудесно! Но не работает... Он в if ругается, что вместо do нужно then. Это поправил. Но после первой же посадки зависает на "воздух". Или бьет меня, если подойти. Если после "print("воздух") -- Впереди воздух" поставить break, то он 1 раз ударит и едет дальше. Такое чувство, что цикл не завершается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Fingercomp 4 409 Опубликовано: 5 декабря, 2015 Чудесно! Но не работает... Он в if ругается, что вместо do нужно then. Это поправил. Но после первой же посадки зависает на "воздух". Или бьет меня, если подойти. Если после "print("воздух") -- Впереди воздух" поставить break, то он 1 раз ударит и едет дальше. Такое чувство, что цикл не завершается. Блин, точно. Я вечно забываю, когда прерывается repeat — в true или false Обновил код, попробуй. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ComST Автор темы 15 Опубликовано: 5 декабря, 2015 Эм... а как? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ComST Автор темы 15 Опубликовано: 5 декабря, 2015 Спасибо! Заработал как надо!!! Буду дальше продолжать надфилем пилить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Alex 4 683 Опубликовано: 5 декабря, 2015 Вот тебе код. function forward() -- проверка блока впереди и движение вперед repeat local smth_ahead, det = r.detect() if det =="entity" then -- если впереди "сущность"... print("живой") -- печатает "Живой" r.swing() -- бьет его, чтобы убежал с поля elseif det == "solid" then -- если впереди твердый блок... print("Блок") r.swing() -- уничтожить блок вперди else print("воздух") -- Впереди воздух break -- на всякий случай end until not smth_ahead r.forward() -- движение вперед на 1 блок end Много лишних телодвижений и операций для форварда. Форвард нужен для того, чтобы двигать робота вперед и как можно быстрее, а крип явно не встречается на каждом шаге робота: function forward() if r.forward() then return true else --[[а вот тут уже че-то начинаем чебучить, проверять, коцать, рубить и т.д., пока хватит дури, через n-е количество попыток неудачных вообще говорим, что там попка какая-то или бедрок и вызываем error, чтобы он там до второго пришествия Христа в цикле бесконечно не тюкал тяпкой деревянной обсидиан --]] end end 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
davial 1 972 Опубликовано: 5 декабря, 2015 (изменено) Ты проверяй на наличие сущности в цикле самом Один раз он сохранил значение — и начинает шприть его. Вот тебе код. function forward() ... end Чудесно! Но не работает... Он в if ругается, что вместо do нужно then. Это поправил. Но после первой же посадки зависает на "воздух". Или бьет меня, если подойти. Если после "print("воздух") -- Впереди воздух" поставить break, то он 1 раз ударит и едет дальше. Такое чувство, что цикл не завершается. Я бы попробовал поменять строку : while det =="entity" do -- если впереди "сущность"... на : while r.detect() == "entity" do -- если впереди "сущность"... А строку local _, det = r.detect() - закоментил или удалил. Тогда робот будет производить проверку в цикле while, значения, которое изменяется постоянно { r.detect() }. А не назначено раз, до цикла и остаётся постоянным в переменной det. Изменено 30 января, 2016 пользователем davial Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ComST Автор темы 15 Опубликовано: 5 декабря, 2015 (изменено) Много лишних телодвижений и операций для форварда. Форвард нужен для того, чтобы двигать робота вперед и как можно быстрее, а крип явно не встречается на каждом шаге робота: function forward() if r.forward() then return true else --[[а вот тут уже че-то начинаем чебучить, проверять, коцать, рубить и т.д., пока хватит дури, через n-е количество попыток неудачных вообще говорим, что там попка какая-то или бедрок и вызываем error, чтобы он там до второго пришествия Христа в цикле бесконечно не тюкал тяпкой деревянной обсидиан --]] end end Т.е. если роботу ничего не мешает двигаться вперед, то и делать ничего не надо, а если мешает - тогда и выяснять причину? Логично. И исходя из твоей логики про бедрок и обсидиан я понял, что робота ведь можно использовать и в пещере. Там пшеница тоже будет расти, главное свет дать. Изменено 5 декабря, 2015 пользователем ComST Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ComST Автор темы 15 Опубликовано: 5 декабря, 2015 (изменено) И так, друзья! Получилось пока следующее: local r = require("robot") local component = require("component") local g = component.geolyzer function prompt_read(prompt) print(prompt) return tonumber(io.read()) end local size = prompt_read("Размер поля: ") -- Задаем размер поля function harvest() -- проверка блока снизу, взрыхление, сбор и посадка саженцев if g.analyze(0).name == "minecraft:wheat" then -- если внизу пшеница... if g.analyze(0).metadata == 7 then -- если пшеница выросла (metadata=7)... r.swingDown() -- срубаем пшеницу. (ПКМ) r.placeDown() -- посадить семена под сабой end else r.swingDown() r.useDown() -- взрыхлить почву под собой (ЛКМ) r.placeDown() -- посадить семена под сабой end end function forward() -- проверка блока впереди и движение вперед if r.forward() then return true else repeat local smth_ahead, det = r.detect() if det == "entity" then -- если впереди "сущность"... print("живой") -- печатает "Живой" r.swing() -- бьет его, чтобы убежал с поля else -- если впереди твердый блок... print("Блок") r.swing() -- уничтожить блок вперди end until not smth_ahead r.forward() -- движение вперед на 1 блок end end function move() -- челночное движение робота по полю for y=1, size do -- движение по ширине от первого ряда до последнего harvest() for x=1, (size-1) do -- движение по дринне от первого блока до последнего forward() -- движение вперед на 1 блок harvest() end if y < size then if y%2 == 1 then -- если ряд не четный... r.turnLeft() -- поворот влево forward() -- движение вперед r.turnLeft() -- поворот влево else r.turnRight() -- поворот вправо forward() -- движение вперет r.turnRight() -- поворот вправо end else end end end function backhome() -- возвращение робота на исходную позицию if size%2 == 1 then -- если не четное кол-во рядов r.turnRight() for z=2, size do forward() end r.turnRight() for z=2, size do forward() end r.turnAround() else r.turnLeft() for z=2, size do forward() end r.turnLeft() end end r.up() r.forward() move() backhome() r.back() r.down() Ставим робота перед передним правым краем будущего поля пшеницы. Запускаем программу. Вводим размер одной стороны поля (оно квадратное). Робот делает свое дело и возвращается на исходную позицию. Если по пути робот встречает препятствие - он его уничтожает (если его можно уничтожить пустой рукой). На данном этапе хотелось бы услышать от вас критику, особенно по размерам кода. Далее будет реализовано: самостоятельный сбор семян перед созданием поля, выращивание других культур, обеспечение "грядок" водой, крафт мотыги и кирки, работа в пещерах с установкой освещения. Если есть еще идеи - с удовольствием выслушаю. Изменено 5 декабря, 2015 пользователем ComST Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах