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

ComST

Пользователи
  • Публикации

    11
  • Зарегистрирован

  • Посещение

  • Победитель дней

    1

Сообщения, опубликованные пользователем ComST


  1. Код, конечно, рабочий, но он монструозный и тяжело воспринимается даже с комментариями

    Вот оно! Надо мне правильно код научится писать. Так что:

    1) Дополню статью алгоритмом разработки шахты и картиночками.

    2) Уберу рекурсию.

    3) Каким-нибудь образом постараюсь сделать код более читабельным. (Правда даже не представляю с чего начать и как это должно выглядеть)

    • Нравится 1

  2. 1) r.detect() вызывается и в том и в другом случае, но результат проверяется лишь во втором, поэтому первый вызов бесполезен.

    2) r.detect() внутри цикла не нужен в любом случае, а предложенная мною замена при проверке -- всего лишь более короткая форма записи, не влияющая на алгоритм работы.

    4) Тут вопрос стоит так. Что будет быстрее? Сначала попытаться двигаться, а при неудаче сломать блок и еще раз попытаться, либо сначала не глядя сломать, а потом двигаться. В большинстве случаев путь робота-шахтера преграждают блоки. Поэтому даже если тратится время на неудачную добычу блока, в среднем по шахте это все равно будет быстрее, чем тратить время на неудачную попытку движения.

     

    P.S.: Поправлю свое сообщение, чтобы не путаться в двух пунктах с номером 3.

    Переписал функцию "forward() по твоему совету.

    function forward() --Движение робота на 1 блок вперед
      if r.forward() then -- Если робот может сделать шаг
        return true -- то хорошо :-)
      else  -- Иначе...
        repeat
          r.swing() -- бъет по объекту впереди
        until not r.detect() -- Впереди чисто?
        forward() -- то шаг вперед
      end
    end
    

    Не знаю, правильно ли вызывать функцию в этой же функции, но всё работает и теперь проверяется. Спасибо!


  3. В большинстве случаев путь робота-шахтера преграждают блоки.

     

    Я провел эксперимент. Внес в код счетчик, сколько раз робот будет "врезаться" во что-то, а потом пытаться убрать это с пути. Итог получился забавный: за всю шахту он "споткнулся" только один раз и то об меня, когда я свалился к нему.

    post-13229-0-82001200-1454270765_thumb.png

    Так что не вижу смысла махать тяпкой перед каждым шагом или за зря проверять есть ли впереди помеха. Если заранее знаешь, что впереди блок (например при рытье тоннеля), то у меня там стоит r.swing(), а потом уже forward(). А если робот возвращается на подзарядку - вря тле там ему что-то помешает. А если и появится какой-то моб, то время на его устранение уйдет меньше, чем проверять каждый раз впереди стоящий блок.


  4. Первое, за что глаз зацепился:

    function forward() --Движение робота на 1 блок вперед
      if r.forward() then -- Если робот может сделать шаг
        return true -- то хорошо :-)
      else  -- Иначе...
        repeat
          r.swing() -- бъет по объекту впереди
          r.detect() -- проверяет остался ли объект
        until r.detect() == false -- Если нет..
        r.forward() -- то шаг вперед
      end
    end
    1) r.detect() внутри repeat/until совершенно бесполезен. Зачем его вызывать, если результат не проверяется?

    2) Конструция r.detect() == false заменяется более компактной not r.detect()

    3) Ошибка: r.forward() сразу за repeat/until не проверяется на успешное действие, поэтому могут быть сбои в движении. Конечно, перед этим была проверка, но между проверкой и действием могли произойти изменения: гравий осыпался, новый моб появился и т.д.

    3) r.forward() в самом начале функции работает крайне неэффективно. Полгода назад я рассказывал об этом Артему (artem211), когда он писал свой геокопатель. Тогда, наверное, во всех найденных мною на этом форуме копалках имелась такая неэффективность. Безуспешная попытка r.forward() занимает столько же времени на выполнение, как и успешное движение. Поэтому продвижение сквозь сплошной массив породы по такому алгоритму замедляет робота почти в два раза.

    Есть два выхода. Самый простой и выбранный Артемом – делать взмах киркой до попытки движения. Почему-то на неудачный взмах кирки время не тратилось. Сейчас может быть иначе, или потом может измениться. Второй вариант более надежный в будущем, но и сложный – анализировать второй параметр, возвращаемый r.detect().

     

    1) Результат проверяется в until r.detect() == false. Здесь он вызывается, а ниже проверяется. Или я чего-то не так понял?

    2) Если я заменю, можно убрать "r.detect() -- проверяет остался ли объект"?

    3) Логично. Надо подумать, как красиво исправить.

    Функция forward() служит исключительно для движения вперед, т.к. не всегда нужно копать перед собой. Если нужно что-то вскопать, это прописывается перед ее вызовом. Но раз там тратится столько времени, r.detect() действительно будет эффективнее.

    Спасибо за замечания! Исправлю.

    До фразы про второстепенные тоннели следует объяснить, что это за тоннели такие, да и вообще хорошо бы кратко описать алгоритм разработки шахты. Тогда и программу будет легче читать.

    Придется картинку нарисовать. У меня не хватает воображения словами это описать.


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

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

    Представляю вашему вниманию программу для робота "Miner" ("Шахтер").

    Робот, с минимальным железом на борту, с помощью данной программы может добывать ресурсы на заданном участке не упустив не единого алмазика (ну или уголька).

     

    Системные требования:

    • Корпус 1-го уровня
    • Процессор 1-го уровня
    • 1 планка памяти 1,5-го уровня (это с запасом)
    • HDD 1-го уровня
    • Видеокарта -1го уровня
    • Lua-BIOS
    • Монитор 1-го уровня
    • Клавиатура
    • Улучшение "Инвентарь"
    • Улучшение "Контейнер" 1-го уровня
    • Геоанализатор

    Дополнения для обслуживания робота:

    • Зарядное устройство
    • Преобразователь энергии
    • Источник энергии
    • Сундук (1-2 шт.)

    Подготовка, установка, настройка и запуск.

    Робот устанавливается на поверхности (можно и в пещере), перед будущей шахтой справа.

    post-13229-0-79041300-1454248519_thumb.png

    Под робота ставится сундук. Сбоку ставится зарядное устройство с источником питания. Например, я использую генератор из IC2 через АКБ, на угле, который добыл робот.

    Роботу необходимо выдать кирку и геоанализатор. Включаем робота и запускаем программу.

    post-13229-0-86186300-1454251623_thumb.png

    Первое что робот спрашивает - это какая у шахты будет ширина. Т.е. это размер второстепенных тоннелей. Мин. значение - 2. Если ввести некорректное значение (<2) или не ввести вовсе, то робот примет значение по умолчанию равное 2.

    Второй вопрос - это длина. Т.е. размер главного тоннеля (от робота прямо по курсу). В связи со спецификой работы робота, введенное значение будет округлено до десятков в меньшую сторону, но не менее 10. Например, если ввести 34, то шахта будет 30 блоков в длину. Значение по умолчанию 10.

    Третий вопрос - глубина шахты. Отсчет ведется от места старта робота. Уровень на котором он стоит = 0, на один блок ниже = 1 и т.д. Например, если робот стоит на уровне 64, а бедрок находится на уровне 1 и вам надо дорыть до него, тогда задайте глубину 62. Так же, если ввести отрицательное значение или не ввести вовсе - значение будет 0.

    И последний вопрос - с какой глубины начать копать. Этот параметр удобен тем, что робот может начать копать с любой глубины, а не от точки старта. Например мне нужны алмазы. Я ставлю робота на поверхность (например высота 64), задаю ему глубину шахты = 59 (т.к. с глубины 5 начинается бедрок, а его робот грызть не умеет) и глубину для начала раскопок = 52 (основные залежи алмазов на глубине 12-5). После старта робот выкопает себе вертикальный тоннель, доберется до начала раскопок и начнет работать. Затем вернется тем же путем.

    После прохода одного уровня (одной высоты), робот возвращается на место старта, вываливает всё что нарыл вниз (надеюсь вы не забыли поставить под него сундук) и заряжается 20 сек. После этого идет на сл. глубину.

    Кстати, чуть не забыл. Робот добывает все блоки, кроме камня, булыжника, земли и гравия.

     

    Достоинства данной программы:

    • Минимальные системные требования
    • Добывает всё под чистую (кроме блэк-листа)
    • Начинает копать с любого уровня
    • Есть немного места для установки дополнительных апгрейдов
    • Из-за встречи с мобом программа не собъется
    • Добывает не только внутри шахты, но и ее внешний слой

    Недостатки:

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

    Планы на будущее:

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

    Просьбы:

    1. Как всегда жду здоровой критики, идей, предложений. Единственное ограничение - это должен быть робот 1-го уровня.
    2. Нужны советы в оптимизации кода.
    3. В коде много комментариев. Это для меня и др. новичков. Так что не пинать.
    4. Если вы знаете подобную программу - покажите ее, пожалуйста. Хочется сравнить. Зашел в соседнюю ветку, посмотрел, опупел. Моя прога еще только в зачатке.
    5. К админам сервера: придумайте, пожалуйста, что-нибудь с лагами на сервере. В сингле программа работает идеально. На сервере - пропускает команды, выполняет их по два раза. В общем жуть. Робот зарывается в такую опу, что приходится его часами искать.

    А! Собственно программа. http://pastebin.com/XkivBpat

    • Нравится 6

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

     

     

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

     

     

     

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

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


  7.  

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

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

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


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

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


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

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

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

     

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

    • Нравится 1
×
×
  • Создать...