Перейти к публикации

В ближайшее время постараюсь разобраться с картой сервера/ЛК/бб кодами

Внимание, с 14 февраля до 20 февраля могут проходить работы на сервере, где также находится лаунчсервер. В связи с этим авторизация в лаунчере может не работать

Вопрос

Я только осваиваю данный язык, прошу не кидаться тапками за незнание. Есть небольшая программа для робота, которая позволяет копать ему блоки(робот стоит на месте). При попытке запуска на новом роботе выбивает ошибку. Устанавливал ОС - robot не смог установить, устанавливал robot - не давало записать файл. Робот в котором сейчас стоит данная прога, работает хорошо и никаких траблов(ставил его не я), с тем человеком нет возможности связаться, а разобраться почему не работает у меня хочется.

local c = require("component")
local robot = require("robot")
local inv = c.inventory_controller
 
while true do
  if robot.durability() <= 0.2 then
    robot.turnAround()
    inv.equip()
    robot.drop()
    os.sleep(15)
    robot.suck()
    inv.equip()
    robot.turnAround()
  end
  c.robot.swing(3)
  os.sleep(0.04)
end

image.png.9c04d42317ccbff20ab1b58dbb96b495.png

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


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

16 ответов на этот вопрос

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

  • 0

Для понимания причин проблемы следует для начала прочитать текст ошибки. Можно воспользоваться автоматическим переводчиком. Это поможет понять, что на строке 6 произошла попытка сравнения значения nil с числом, что недопустимо. Глядя на шестую строку, можно заметить условие robot.durability() <= 0.2, где явное число сравнивается с предположительным числом. Но функция может возвратить что-то иное, и, судя по всему, тот самый nil. Теперь следует задаться вопросом, в каком случае может быть возвращено значение nil. Логично предположить, что это возможно либо в случае полного отсутствия предмета в слоте инструмента, либо в слоте находится и не инструмент вовсе, что и подтверждается документацией https://ocdoc.cil.li/api:robot.

 

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

  • Like 2

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


Ссылка на сообщение
Поделиться на других сайтах
  • 0
6 минут назад, eu_tomat сказал:

в случае отсутствия инструмента

но запускал я его с буром, сейчас попробую с обычной киркой

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


Ссылка на сообщение
Поделиться на других сайтах
  • 0
3 минуты назад, Alexhotice сказал:

но запускал я его с буром, сейчас попробую с обычной киркой

С каким буром? Буры из IC2 вроде без проблем определяются.

И какая используется версия OpenComputers?

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


Ссылка на сообщение
Поделиться на других сайтах
  • 0
3 минуты назад, eu_tomat сказал:

Буры из IC2 вроде без проблем определяются

да, это был мой косяк, я закинул в инвентарь вместо руки и думал почему оно не работает

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


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

И такой вопрос еще: почему робот скидывает бур в сундук сверху вместе со всем содержимым хотя у меня стоит сброс сзади в мфэх?

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


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

В этой программе я вообще не увидел кода для сброса содержимого инвентаря.

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


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

У меня высасывание идет шинами

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


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

Тогда понятно. Шина, стоящая сверху, быстро высасывает инвентарь робота, сразу как только выполнится перенос инструмента в инвентарь с помощью inv.equip(). И перенос инструмента в зарядник с помощью robot.drop() выполниться просто не успевает.

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


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

а как можно дополнить, чтобы тогда робот сам скидывал свой инвентарь кроме бура, допустим в сундук сбоку?

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


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

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

 

Например, можно удалить зарядник на один блок от робота. И тогда робот будет перемещаться на одну клетку из-под шины.

 

А можно перемещать содержимое инвентаря роботом в стоящий сверху него сундук программным путём, а шиной высасывать уже содержимое сундука. С тем же успехом сундук можно разместить и внизу и слева и справа, главное, не давать шине неконтролируемо высасывать инвентарь робота.

 

Также можно разместить зарядник слева от робота, а шину разместить позади робота. Тогда шина сможет извлекать содержимое робота только тогда, когда он ориентирован к ней задом. При повороте налево к заряднику шина окажется слева и будет иметь доступ только к слотам улучшений, и слот инструмента со слотами внутреннего инвентаря будут для шины недоступными. В это время робот может выполнить все необходимые манипуляции с инструментом, после чего вернуться в исходную позицию.

 

В общем, можно придумать множество работоспособных конфигураций.

  • Like 3

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


Ссылка на сообщение
Поделиться на других сайтах
  • 0
20 часов назад, Alexhotice сказал:

а как можно дополнить, чтобы тогда робот сам скидывал свой инвентарь кроме бура, допустим в сундук сбоку?

Похоже, я не с первого раза понял вопрос.

 

Требуется уточнить, что это за механизм, чтобы выбрать эффективный вариант проверки заполнения инвентаря. Это генератор булыжника?

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


Ссылка на сообщение
Поделиться на других сайтах
  • 0
10 минут назад, eu_tomat сказал:

Похоже, я не с первого раза понял вопрос.

 

Требуется уточнить, что это за механизм, чтобы выбрать эффективный вариант проверки заполнения инвентаря. Это генератор булыжника?

нет, один робот ставит руду, второй ломает эту руду буром с удачей. Робот у которого у меня возник вопрос ломает

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


Ссылка на сообщение
Поделиться на других сайтах
  • 0
11 часов назад, Alexhotice сказал:

нет, один робот ставит руду, второй ломает эту руду буром с удачей. Робот у которого у меня возник вопрос ломает

Зачем так сложно то? С такой задачей может справиться робот в одиночку. Как я считаю тут надо 2 сундука. Например сверху будет руда, а вниз будет сбрасывать осколки.

Алгоритм работы прост до безобразия.

  • Засосать 1 стак руды в 1 слот
  1. Поставить блок руды, срубить его
  2. Повторять пока не закончится руда
  • Очистить весь инвентарь
  • (опционально) повернуться направо/налево выполнить обслуживание бура, вернуться на исходную

Вроде и все. Даже робота 1 уровня хватит на такую неказистую работу.

Вот пожалуйста набросал за пару минут, правда без заправки.

  • Like 1

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


Ссылка на сообщение
Поделиться на других сайтах
  • 0
12 часов назад, Alexhotice сказал:

нет, один робот ставит руду, второй ломает эту руду буром с удачей. Робот у которого у меня возник вопрос ломает

Это сложнее. Тут появляется множество вариантов, эффективных в своих условиях и при этом неэффективных в других. И какие условия возникли конкретно у тебя, я не знаю. но я попробую объяснить суть проблемы.


В случае генератора булыжника есть только один непрерывно добываемый малоценный ресурс.


Если сундук находится над или под роботом, то оптимизация сводится к тому, чтобы перемещать ресурсы полными стаками. Робот перемещает хоть один предмет из слота, хоть полный стак за одинаковое время. А это значит, что выгодно перемещать наиболее полный стак. Заполнение слота легко отслеживается.


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


Гораздо больше вопросов вызывает перелопачивание руды киркой.


С точки зрения оптимизации действий робота он должен выгружать свой инвентарь, когда хоть-что появится в последнем слоте. А если речь идёт о рудах GT, где может выпасть вторичный ресурс, то сигналом для выгрузки будет появление предмета в предпоследнем слоте.


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


Но тут возникает новый подводный камень. Эта схема удобна в случае огромного количества руды. У неё есть большой потенциал на поздних стадиях уже упомянутого GT. Но в начале игры, когда ресурсов мало, робот будет ждать полного заполнения своего инвентаря, долго не отдавая переработанные ресурсы, что неудобно.


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


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

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


Ссылка на сообщение
Поделиться на других сайтах
  • 0
1 час назад, eu_tomat сказал:

Это сложнее. Тут появляется множество вариантов, эффективных в своих условиях и при этом неэффективных в других. И какие условия возникли конкретно у тебя, я не знаю. но я попробую объяснить суть проблемы.


В случае генератора булыжника есть только один непрерывно добываемый малоценный ресурс.


Если сундук находится над или под роботом, то оптимизация сводится к тому, чтобы перемещать ресурсы полными стаками. Робот перемещает хоть один предмет из слота, хоть полный стак за одинаковое время. А это значит, что выгодно перемещать наиболее полный стак. Заполнение слота легко отслеживается.


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


Гораздо больше вопросов вызывает перелопачивание руды киркой.


С точки зрения оптимизации действий робота он должен выгружать свой инвентарь, когда хоть-что появится в последнем слоте. А если речь идёт о рудах GT, где может выпасть вторичный ресурс, то сигналом для выгрузки будет появление предмета в предпоследнем слоте.


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


Но тут возникает новый подводный камень. Эта схема удобна в случае огромного количества руды. У неё есть большой потенциал на поздних стадиях уже упомянутого GT. Но в начале игры, когда ресурсов мало, робот будет ждать полного заполнения своего инвентаря, долго не отдавая переработанные ресурсы, что неудобно.


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


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

Я сделал гораздо легче(Так как я понимал и знал как сделать), один робот ставит руду, которая попадает в него с МЭ системы, второй срубает ее и закидывает обратно в МЭ систему. Проблему с высасыванием бура решил постановкой в шинах фильтра на те руды

 

Робот который ставит:

local c = require("component")
local robot = require("robot")
while true do
  c.robot.place(3)
  os.sleep(0.05)
end

Робот который ломает:

local c = require("component")
local robot = require("robot")
local inv = c.inventory_controller
 
while true do
  if robot.durability() <= 0.2 then
    robot.turnAround()
    inv.equip()
    robot.drop()
    os.sleep(15)
    robot.suck()
    inv.equip()
    robot.turnAround()
  end
  c.robot.swing(3)
  os.sleep(0.04)
end

Вот так они стоят:

1077869153_.gif.87ff025c2ac723d5f2364b63e5138a7d.gif

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

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


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

Ну может так и удобнее для вас будет. Но попробуйте на одном роботе, как я в GIF показывал. Уверен вы будете приятно удивлены скоростью работы. Всетаки лучше 1 паузу сделать, чем ожидать пока роботы синхронизируют свою работу.

--https://i.imgur.com/9aw0a6E.gifv
--блоки руды сверху в сундук закидывать
--сыпуху вниз будет скидывать
--перед роботом не забудьте поставить подставку, так будет точнее ставить

local r = require('robot')

while true do
  r.select(1)
  if r.suckUp(64) then
    local rep = r.count(1)

    for i=1,rep do
      r.place()
      while not r.swing() do
        os.sleep(0)
      end
    end

    for i=1, r.inventorySize() do
      if r.count(i) > 0 then
        r.select(i)
        r.dropDown(64)
      end
    end
  else
    os.sleep(15)
  end
end

П.с. Удивительно но я же свою программу щас использую...

Изменено пользователем Asior
  • Like 2

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


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

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

×