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

serafim

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

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

  • Посещение

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

    46

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


  1. 1 минуту назад, eu_tomat сказал:

    Можешь скинуть пример кода для демонстрации этого эффекта?

    Происходит это при работе карьера, но не всегда.

    В ранних версиях использовал код такого вида:

    Скрытый текст
    
    local e = {require("event").pull("key_down")}
    if e[4] == 49 then
      print("программа завершена")
      os.exit()
    elseif e[1] == "key_down" then
      print("нажата кнопка")
    end

     

    Робот возвращался к старту, и по событию key_down должен был продолжить копать,

    но в итоге он приезжал и сразу ехал обратно


  2. 1 час назад, eu_tomat сказал:

    очень странно, что событие inventory_changed вообще генерируется при установке блока.

    Событие "key_down" также временами срабатывает без нажатия кнопок, приходится дополнительно его проверять.


  3. 14 минуты назад, eu_tomat сказал:

    Под этим предлогом можно было бы удалить многие темы нашего форума

    может и так, тогда предлагаю отправить данную тему в корзину

    там можно будет её смотреть, но нельзя редактировать

    либо добавить на сайт новую ветку лагодромы рядом с корзиной, закрытую от редакции


  4.  

    Начнём пожалуй с самого начала, для оптимизации программы разберём предложенный код поэтапно

    Скрытый текст
    
    local sides = require "sides"
    local robot = require "robot"
    local component = require "component"
    local active_slot = 1
    size=robot.inventorySize()
    local function Text()
        os.execute("cls")
        print("РОБОТ РАБОТАЕТ!! Создатель - GooodGame")
        print("Доработал-atomzerg")
    end
     
    Text()
     
     
    while true do
    robot.select(active_slot)
    if robot.count(active_slot) == 0 then
        active_slot = active_slot + 1 end
      if robot.select(active_slot) ==size then
       active_slot = 1 end
    if robot.place() == false then active_slot = active_slot + 1 end
    if active_slot == size then active_slot = 1 end
    robot.place()
    end

     

    1 local sides = require "sides"

    библиотека sides на 1й строке - этот интерфейс предоставляет таблицу названий, для работы со сторонами блоков

    в формате:  Низ (bottom): 0 , Верх (top): 1 , Тыл (back): 2 , Перед (front): 3 , Право (right): 4 , Лево (left): 5

    пример для работы с контроллером красного камня: 

    1 local component = require("component")
    2 local sides = require("sides")
    3 local rs = component.redstone
    4 rs.setOutput(sides.left,15)

    здесь использован rs.setOutput(sides.left,15) на 4й строке (включить сигнал с лева, с силой сигнала 15),

    без библиотеки sides пришлось бы указать сторону в формате rs.setOutput(5,15)

    • Вот только в коде эта библиотека не используется, вызывать её не требуется
    3 local component = require "component"

    библиотека component на 3й строке - этот интерфейс используется для доступа и взаимодействия компьютера с компонентами

    тот же пример для работы с контроллером красного камня:

    1 local component = require("component")
    2 local rs = component.redstone

    для того чтоб взаимодействовать с контроллером красного камня необходимо его назначить компонентом 

    2 local rs = component.redstone
    • Вот только ни какие взаимодействия с компонентами в коде не происходят,  вызывать её не требуется
    5 size=robot.inventorySize()

    глобальная переменная size на 5й строке вызывается один раз при запуске программы

    и принимает значение последнего слота в инвентаре робота,

    который при одном улучшении инвентаря равен 16 ячейкам

    • желательно назначать переменные локально
    5 local size = robot.inventorySize()
    • чтобы она не вносила изменения в другие программы за пределами данного кода
    6 local function Text()
    7    os.execute("cls")
    8    print("РОБОТ РАБОТАЕТ!! Создатель - GooodGame")
    9    print("Доработал-atomzerg")
    10 end
     
    12 Text()
    • функция Text() вызывается только один раз на строке 12, её можно упростить
    7 os.execute("cls")
    8 print("РОБОТ РАБОТАЕТ!! Создатель - GooodGame")
    9 print("Доработал-atomzerg")
    • также вопрос а требуется ли она вообще, достаточно указать что за программа сейчас работает
    print("работает установщик блоков")

    теперь касательно основного тела программы:

    16 robot.select(active_slot)
    17 if robot.count(active_slot) == 0 then
    18    active_slot = active_slot + 1 end
    19  if robot.select(active_slot) ==size then
    20   active_slot = 1 end
    21 if robot.place() == false then active_slot = active_slot + 1 end
    22 if active_slot == size then active_slot = 1 end
    23 robot.place()
    • текущий алгоритм работы:

    строка 16  выбирается активный слот инвентаря робота из переменной active_slot , при первом запуске она равна 1

    строка 17  проверяется значение слота (в данном случае 1) и если он пустой то

    строка 18  к глобальной переменной active_slot плюсуется 1

    строка 19  если выбран последний слот инвентаря робота то

    строка 20  переменная active_slot меняет значение на 1

    строка 21  если робот не смог поставить блок то к активному слоту плюсуется 1

    строка 22  если переменная active_slot равна последнему слоту робота то переменная active_slot меняет значение на 1

    строка 23  робот ставит блок без проверок успешно или нет

    • Вывод: в текущем алгоритме творится каша

    использован не оптимальный метод выбора заполненного слота назначая переменную active_slot

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

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

    поставил его раньше, в итоге будет постоянно перебирается инвентарь тратя время в пустую

     

    отдельно хотелось бы обратить внимание на форматирование кода, читать его затруднительно

    общепринято использовать для lua два пробела, да это не обязательно но сильно улучшает восприятия написанного кода

    второе - это как написаны логические элементы, тут не выделены начало и конец а также выполняемые условия

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

     

    вот так должен был выглядеть код при соблюдении общепринятых норм

    while true do
      robot.select(active_slot)
      if robot.count(active_slot) == 0 then
        active_slot = active_slot + 1 
      elseif robot.select(active_slot) == size then
        active_slot = 1 
      elseif robot.place() == false then 
        active_slot = active_slot + 1 
      elseif active_slot == size then 
        active_slot = 1 
      end
      robot.place()
    end
    • Использовать кучу условий и метод счётчика для выбора заполненного слота в инвентаре робота не эффективно

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

    и при нахождении полного слота выбрать его, остановив дальнейший перебор

    for slot = 1, inv do
      if r.count(slot) > 0 then 
        r.select(slot)
        break
      end
    end

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

    if r.count() == 0 then

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

    правильнее остановить поиск, пока в инвентаре не появится новые блоки,

    и при добавлении новых блоков, сразу его выбрать

    if slot == inv then
      local e, slot = event.pull("inventory_changed")   
      r.select(slot)
    end

    проверять поставил ли робот блок нет необходимости

    if robot.place() == false then 

    особенно если использованы несколько установщиков блоков, программа будет простаивать

    r.place()

    Собственно готовый код занимает всего 21 строку, осталось его только собрать до кучи

     

    Но я этого делать не буду, и вот почему:

    Эта программа при лагающем сервере вызывает рассинхрон при быстрой смене блока,

    устанавливая и разрушая его сервер выдаёт финты типа моментального разрушения или дюпа

     

    Подобные действия не способствуют популезации мода OpenComputers

    Рекомендую проголосовать за удалении этой темы как потенциально нежелательной

    • Нравится 1
    • В шоке 1

  5. 22 минуты назад, eu_tomat сказал:

    Каков смысл общего блока для совместной работы двух роботов, если у каждого есть свой инструмент для рубки?

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

    22 минуты назад, eu_tomat сказал:

    Какой способ хорош? Мой с тремя установщиками и одним рубщиком?

    Твой, но увы тут ПО писать особо не о чем


  6. 9 минут назад, eu_tomat сказал:

    А в чём заключается преимущество именно такой схемы параллельной работы?

    Идея в том чтоб не заморачиваться с ПО, роботы сами будут ставить или рубить руду в зависимости от того кто раньше успеет

    9 минут назад, eu_tomat сказал:

    три робота устанавливали руду в один общий блок, а четвёртый рубил руду в этом блоке.

    Такой способ тоже хорош и экономный в плане инструмента и зарядчика

    9 минут назад, eu_tomat сказал:

    что даёт этот трюк с общим блоком в схеме на двух независимых роботах, когда каждый из них рубит своим инструментом?

    Тут прироста увы нет, в основном влияет только время установки блока


  7. Синхронизировать двух роботов на одну задачу оказалось не так просто как думалось,

    перепробовал пол сотни вариантов пока получилось хоть что-то не сильно лагучее

     

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

    Скрытый текст

    RKp7qhk.gif

    вид сзади

    Скрытый текст

    WcNqRXO.png

    собственно ссылка на это недоразумене https://pastebin.com/FvGE1qYa

     

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

     

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

     

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

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


  8. форматирование немного съезжает, поправил по 2 пробела

    Скрытый текст
    
    --CycleBlockBreaker for EEPROM
    --Original OpenOS version by Asior (Asioron)
    --Expanded EEPROM version by Bs()Dd
    
    --[[Minimum requirements:
        *Robot - 1 tier
        In robot:
            *CPU - 1 tier
            *1x Memory - 1 tier
            *Inventory Upgrade
            *EEPROM with flash this code
            *Mining tool
        *Computer with OpenOS for flashing EEPROM
        
        Place the chest on top and put blocks there
        Place the chest at the bottom, there will be loot from blocks
    ]]
    r = component.proxy(component.list("robot")())
    c = component.proxy(component.list("inventory_controller")())
    inv = r.inventorySize()
    
    speaker = false --Set true for using speaker when something is gone wrong
    lowcharge = 0.005 --Set there number maximal working charge in durability() format
    
    --Needs Inventory Controller
    autocharge = false --Set there number of turns right to charger (for charging tools)
    chargesleep = 15 --Set there number of sleep duration while tool is charging
    
    function turnNcharge()
      for i = 1, autocharge do
        r.turn(true)
      end
      c.equip()
      r.drop(3, 1)
      local ws = computer.uptime() + chargesleep
      repeat
        computer.pullSignal(ws - computer.uptime())
      until computer.uptime() >= ws
      r.suck(3, 1)
      c.equip()
      for i = 1, autocharge do
        r.turn(false)
      end
    end
    
    while true do
      local rep = r.suck(1, 64)
      if rep then
        for i = 1, rep do
          while not r.place(3) do
            if speaker then
              computer.beep(1100, 0.5)
            else
              computer.pullSignal(0)
            end
          end
          while not r.swing(3) do
            if speaker then
              computer.beep(1000, 0.5)
            else
              computer.pullSignal(0)
            end
          end
          if r.durability() then
            while r.durability() < lowcharge do
              if autocharge then
                turnNcharge()
              else
                if speaker then
                  for i = 1, 10 do
                    computer.beep(700, 0.5)
                  end
                else
                  local ws = computer.uptime() + 5 --Wating 5 sec, then trying to drop blocks again
                  repeat
                    computer.pullSignal(ws - computer.uptime())
                  until computer.uptime() >= ws
                end
              end
            end
          end
        end
        for i = 1, inv do
          if r.count(i) > 0 then
            r.select(i)
            while not r.drop(0, 64) or r.count(i) > 0 do
              if speaker then
                for i = 1, 10 do
                  computer.beep(700, 0.5)
                end
              else
                local ws = computer.uptime() + 5 --Wating 5 sec, then trying to drop blocks again
                repeat
                  computer.pullSignal(ws - computer.uptime())
                until computer.uptime() >= ws
              end
            end
          end
        end
      else
        if speaker then
          for i = 1, 10 do
            computer.beep(500, 0.5)
          end
        else
          local ws = computer.uptime() + 5 --Wating 5 sec, then trying to get blocks again
          repeat
            computer.pullSignal(ws - computer.uptime())
          until computer.uptime() >= ws
        end
      end
    end

     

     а так вроде норм


  9. Использование робота для установки схемы в реактор:

    • Поставьте робота лицом к реактору IC2 типа "звёздочка"  (реактор в центре + 6 реакторных камер вокруг)
    • Положите в инвентарь роботу компоненты реактора предполагаемой схемы:
    Скрытый текст

    Qu8VAYM.png

     

    SOJWbw5.png

     

    7a9rsTf.png

     

    5GtW2RI.png

    • Список что требуется и чего не хватает будет указан на экране робота
    Скрытый текст

    GxOR7xv.gif

    • Введите имя программы и укажите схему из предложенных на экране (360,420,1056,1308 eu/t)

                   также можно запустить программу передав атрибуты, например r 1308

     

                   версия для IC2 1.7.10 https://pastebin.com/xWhYcrgM или pastebin get xWhYcrgM r

                   версия для IC2 1.12.2 https://pastebin.com/LYDve4ai  или  pastebin get LYDve4ai r 

           

    • Во время выполнения программы разрешено произвольно добавлять и убирать компоненты в инвентаре робота
    • Во время выполнения программы запрещено заменять компоненты в инвентаре робота, а также самому добавлять их в реактор
       
    • Нравится 2

  10. 18 часов назад, eu_tomat сказал:

    дописать короткую инструкцию, как игроку обращаться с этой программой

    в принципе можно

     

    18 часов назад, demongts1998 сказал:

    есть схемки для реакторов получше

    предложи варианты


  11. обнова https://pastebin.com/xWhYcrgM

    Скрытый текст

    GxOR7xv.gif

    добавил динамический список недостающих компонентов в инвентаре робота

    перевёл прогу на gpu так как в консоли творилась каша

    выход из проги кнопкой ctrl

     

    • Нравится 2

  12. 3 часа назад, eu_tomat сказал:

    Или на сервере какие-то особенности приватов не позволяют так обращаться с внешними инвентарями?

    мене тоже смущает этот вопрос, очень часто робот в привате имеет ограничения и robot.drop() предпочтительней

    7 минут назад, eu_tomat сказал:

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

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


  13. 1 час назад, serafim сказал:

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

    изваял обработчик событий

    Скрытый текст
    
    local event = require("event")
    
    while true do
      local e = {event.pull("inventory_changed")}
      for i = 1, #e do
        if e[i] then
          print(i..": "..e[i])
        else
          print(i..": nil")
        end
      end
      print(" ")
    end

     

    событие inventory_changed возвращает только 2 параметра

    1: inventory_changed -- событие изменения инвентаря
    2: 7                 -- номер слота

    обновил прогу на

      ...
    local e, slot = event.pull("inventory_changed")     
    if slot and r.count(slot) > 0 then
      ...

    теперь событие inventory_changed отрабатывает адекватно


  14. 2 часа назад, eu_tomat сказал:

    отказавшись от выполнения getStackInInternalSlot(slot) для заведомо пустых ячеек. Наличие предмета в слоте помогает определить функция robot.count(slot), и работает она очень быстро

    изначально поиск был по имени через string.find() в итоге от него отказался, так пользователю проще будет понят что за компонент в шаблоне от него хотят. Насчёт что через robot.count(slot) быстрее, как то не замечал, ок учту

    2 часа назад, eu_tomat сказал:

    robot.inventorySize() вызывается больше одного раза

    ок, вынесу в начало

    2 часа назад, eu_tomat сказал:

    При поступлении сигнала inventory_changed программа заново сканирует инвентарь

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

    перед повторный сканированием прога ждёт 5 секунд, за этот промежуток могут добавится ещё компоненты и в другие слоты, поэтому повторно делаем скан всего инвентаря

    2 часа назад, eu_tomat сказал:

    При обнаружении отсутствующего компонента в инвентаре робота необязательно тратить время только лишь на ожидание его появления поэтому вместо robot.drop() можно использовать component.inventory_controller.dropIntoSlot(side,slot,count), помещая предмет строго в нужный слот.

    да так ещё лучше, может сделаю

    2 часа назад, eu_tomat сказал:

    Если использовать dropIntoSlot допустимо, то заранее сканировать инвентарь робота имеет смысл только для того, чтобы сообщить об отсутствующих игроку компонентах

    такой метод в корне меняет логику проги, и да так удобней

    2 часа назад, eu_tomat сказал:

    Обнаружение изменения инвентаря сейчас реализовано проверкой на 0 значения robot.count(slot). Это работает только для случая извлечения предмета из слота. Но игрок может произвести замену предмета. В этом случае программа рискует поместить в реактор не тот компонент.

    в таком случае придётся повторно запрашивать имя компонента тратя кучу времени

    2 часа назад, eu_tomat сказал:

    Зачем функция set сделана рекурсивной? В чём удобство именно рекурсивной функции?

    чтоб цикл для выставления схемы в реактор не выполнялся пока в реактор не попадёт нужный компонент

    также нужно передавать ряд параметров функции set (имя компонента, наличие компонента в инвентаре, также если инвентарь пуст то цикл в функции set не выполняется приходится ожидать пока компоненты добавят)

    возможно можно избавится от рекурсии, но пока реализовал так как мне казалось проще 


  15. обновил

    теперь если прога не найдёт компонент в инвентаре с прошлого скана, заново обновит скан

    если компоненты добавятся в процессе работы, то прога сначала выложит те что уже были в скане, а затем попытается найти недостающие

    время кстати не изменилось 33-34 сек при 54 компонентах в инвентаре робота


  16. 2 минуты назад, eu_tomat сказал:

    если игрок  извлекает предметы из инвентаря робота в процессе загрузки компонентов в реактор, то правильность работы программы не гарантируется.

    можно проверять перед отправкой в реактор если ли компонент в инвентаре от предыдущего скана

     

    обнова

    теперь прога принимает атрибуты, вводить так:  название проги пробел схема   test 1320

    при недостающем компоненте теперь пишет его название на русском

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