Перейти к содержимому
ComST

Программа "Фермер"

Рекомендуемые сообщения

Здравствуйте, друзья мои!

Написал я тут намедни программу "Фермер". Классический вариант начинающего программиста: вскопал, посадил, собрал, посадил заново.

Но мне показалось этого мало. Решил доработать надфилем, что бы робот был полностью самостоятельным. На данный момент робот делает следующее: удаляет лишние блоки земли и травы, взрыхляет почву (размер поля задается в программе), сажает семена, проверяет выросла ли пшеница, срубает выросшую, сажает заново, гоняет мобов с поля. Всё бы хорошо, но вот с последним пунктом у меня проблема. Для большей ясности приведу код:

 

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. Робот себе спокойно копает, я встаю у него спереди. Соответственно он начинает меня бить тяпкой, до тех пор, пока не убьет или я не отвалю с пути. Когда я отхожу в сторону, робот не выходит из цикла. Я уже себе голову сломал почему. Есть подозрение, что блок перед роботом не обновляется. Но это уже крайность. Кто что может подсказать? Заранее спасибо!

Изменено пользователем ComST

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Здравствуйте, друзья мои!

Написал я тут намедни программу "Фермер". Классический вариант начинающего программиста: вскопал, посадил, собрал, посадил заново.

Но мне показалось этого мало. Решил доработать надфилем, что бы робот был полностью самостоятельным. На данный момент робот делает следующее: удаляет лишние блоки земли и травы, взрыхляет почву (размер поля задается в программе), сажает семена, проверяет выросла ли пшеница, срубает выросшую, сажает заново, гоняет мобов с поля. Всё бы хорошо, но вот с последним пунктом у меня проблема. Для большей ясности приведу код:

 

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
Изменено пользователем Fingercomp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

:D  Чудесно! Но не работает... Он в if ругается, что вместо do нужно then. Это поправил. Но после первой же посадки зависает на "воздух". Или бьет меня, если подойти.

Если после "print("воздух") -- Впереди воздух" поставить break, то он 1 раз ударит и едет дальше. Такое чувство, что цикл не завершается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

:D  Чудесно! Но не работает... Он в if ругается, что вместо do нужно then. Это поправил. Но после первой же посадки зависает на "воздух". Или бьет меня, если подойти.

Если после "print("воздух") -- Впереди воздух" поставить break, то он 1 раз ударит и едет дальше. Такое чувство, что цикл не завершается.

Блин, точно. Я вечно забываю, когда прерывается repeat — в true или false :)

Обновил код, попробуй.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо! Заработал как надо!!! Буду дальше продолжать надфилем пилить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вот тебе код.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

Ты проверяй на наличие сущности в цикле самом ;)

Один раз он сохранил значение — и начинает шприть его.

Вот тебе код.

function forward() 
...
end

 

:D  Чудесно! Но не работает... Он в if ругается, что вместо do нужно then. Это поправил. Но после первой же посадки зависает на "воздух". Или бьет меня, если подойти.

Если после "print("воздух") -- Впереди воздух" поставить break, то он 1 раз ударит и едет дальше. Такое чувство, что цикл не завершается.

Я бы попробовал поменять строку :

while det =="entity" do -- если впереди "сущность"...

на :

while r.detect() == "entity" do -- если впереди "сущность"...

 

А строку local _, det = r.detect()  - закоментил или удалил.

 

Тогда робот будет производить проверку в цикле while, значения, которое изменяется постоянно { r.detect() }. А не назначено раз, до цикла и остаётся постоянным в переменной det.

Изменено пользователем davial

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

Много лишних телодвижений и операций для форварда. Форвард нужен для того, чтобы двигать робота вперед и как можно быстрее, а крип явно не встречается на каждом шаге робота:

function forward()
  if r.forward() then 
    return true
  else
      --[[а вот тут уже че-то начинаем чебучить, проверять, коцать, рубить и т.д., пока хватит дури, через n-е количество попыток неудачных вообще говорим, что там попка какая-то или бедрок и вызываем error, чтобы он там до второго пришествия Христа в цикле бесконечно не тюкал тяпкой деревянной обсидиан --]]
  end
end

Т.е. если роботу ничего не мешает двигаться вперед, то и делать ничего не надо, а если мешает - тогда и выяснять причину? Логично. И исходя из твоей логики про бедрок и обсидиан я понял, что робота ведь можно использовать и в пещере. Там пшеница тоже будет расти, главное свет дать.

Изменено пользователем ComST

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

И так, друзья! Получилось пока следующее:

 

 

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()

 

 

 

Ставим робота перед передним правым краем будущего поля пшеницы. Запускаем программу. Вводим размер одной стороны поля (оно квадратное). Робот делает свое дело и возвращается на исходную позицию. Если по пути робот встречает препятствие - он его уничтожает (если его можно уничтожить пустой рукой). На данном этапе хотелось бы услышать от вас критику, особенно по размерам кода.

Далее будет реализовано: самостоятельный сбор семян перед созданием поля, выращивание других культур, обеспечение "грядок" водой, крафт мотыги и кирки, работа в пещерах с установкой освещения. Если есть еще идеи - с удовольствием выслушаю.

Изменено пользователем ComST

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...