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

eu_tomat

Модераторы
  • Публикации

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

  • Посещение

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

    331

Все публикации пользователя eu_tomat

  1. Можешь скинуть пример кода для демонстрации этого эффекта?
  2. А при каких условиях оно генерируется кроме, собственно, нажатия кнопок?
  3. Тут ещё не помешает проверка на наличие предмета в слоте, т.к. по завершении обработки 64 блоков руды очередь гарантированно забьётся событиями извлечения предмета из слота, из-за чего с большим шансом слоты, на которые указали сигналы, могут оказаться пустыми. Кстати, очень странно, что событие inventory_changed вообще генерируется при установке блока. Причём, аж 4 раза . Не должно быть ни того, ни другого. Оно должно вызваться один раз при исчерпании стака, как при выбрасывании предметов по одной штуке. Проверялось для OpenComputers-MC1.7.10-1.7.5.1290-universal.jar.
  4. eu_tomat

    quarry карьер

    Ого! Да тут кроме основной программы целая коллекция вспомогательных! Использовать их совершенно необязательно, но при использовании копалки любая из них может пригодиться.
  5. @serafim Хороший анализ плохого кода, я согласен почти с каждым утверждением. Но в удалении этой темы я не вижу смысла. В ней разобраны альтернативные варианты решения поставленной задачи, более экономно расходующие ресурсы сервера. Обсуждение проблемы лагодромов я считаю полезным. Большинство игроков создаёт лагодромы ненамеренно, т.к. попросту не знает, как писать программы правильно, как минимизировать нагрузку на сервер. Таким игрокам будет полезна информация о том, как решить задачу правильно. А тот, кто вредит серверу целенаправленно, готов использовать для этого любые другие моды, а не только OC. И останавливает такого игрока только одно средство — бан. Конечно же, не стоит выкладывать готовые скрипты для причинения вреда серверу. Но также не стоит и препятствовать обсуждению плохо спроектированного кода из опасений, что оно будет содержать намёки на возможность создания явно вредоносных программ. Под этим предлогом можно было бы удалить многие темы нашего форума. Но что нам это даст?
  6. Для информации, чтобы читателям было понятно, что здесь происходит: @serafim выложил свои варианты программ, но пока решил притормозить, чтобы не участвовать в создании лагодромов. Его позиция понятна, темы автора заказа вызывают противоречивые чувства.
  7. Начнём с установщика блоков: Предварительный, грубый анализ: Программа в основном расходует время на выполнение бесконечного цикла. Внутри бесконечного цикла безусловно выполняются следующие операции: Два раза выполняется robot.select, затрачивая 0.05 сек на вызов. Один раз robot.place, затрачивая 0.4 сек на вызов Один раз robot.count, на вызов тратится примерно 5E-5 сек времени. Успешные вызовы robot.place приближают игрока к цели, нет смысла уменьшать количество этих вызовов, но есть смысл подготовить робота таким образом, чтобы каждый вызов был успешным, т.к. выполнение неудачного вызова требует 0.05 сек времени. Программа проверяет успешность операции кодом: if robot.place() == false, но из этого делается неверный вывод, будто бы закончились предметы в слоте. Это не верно. Такое условие сообщает о том, что не удалось установить блок в мир: скорее всего, есть какая-то помеха. Для проверки наличия предмета в слоте могло бы подойти условие if robot.place() == nil, но эту проверку можно гораздо быстрее осуществить с помощью robot.count(). В случае же, если не удалось установить блок, имеющийся в слоте робота, требуется просто подождать, пока освободится пространство в координатах установки. Также неудача при установке блока возможна в случае, когда в инвентарь робота попал предмет, не являющийся блоком. Но это уже проблема корректности настройки фильтров в логистических сетях на базе игрока. Думаю, этот вариант вообще не имеет смысла анализировать в программе. Вызовы robot.select() приближают игрока к цели только в том случае, если текущий слот инвентаря опустел. И при достаточно быстром заполнении инвентаря робота блоками руды требуется не более 1/64 этой операции на одну итерации цикла. Минимизируя количество вызовов этой операции удастся сэкономить 0.05*2 - 0.05/64 секунд на одну итерации цикла. Относительно времени, затраченного на основную операцию, экономия составит 19.84%.
  8. @Alex_Bolkov Что именно там должно быть зациклено? Надо сделать всё то же самое, только в бесконечном цикле? Тогда вместо этой строки: Repeat() Пишем: while true do Repeat() end
  9. @serafim Ну, ясно. Нет особого смысла направлять роботов в один блок, если речь не идёт об экономии на дорогом инструменте. Теперь вернёмся к теме заказа. Меня эта задачка заинтересовала своей экстремальностью, поэтому я потратил много времени на исследование способов, позволяющих достичь максимальной скорости переработки руды. Мы с автором заказа обсуждали в дискорде возможные варианты, но он отверг все предложенные мной улучшения схемы. Он сопротивляется каким-либо изменениям изначальной схемы и разрешает только оптимизировать код программ. При таких условиях для меня это совершенно неинтересная задача с точки зрения кодинга. Но благодаря примитивности эти двух программ я считаю их хорошими примерами для оптимизации. Если я и перепишу эти две программы, то это будет в формате блога с раскрытием темы оптимизации. Если же тебе интересна задача, ты можешь сделать это раньше меня и без лишних слов, аккуратно с нуля написав обе программы, не используя лишних операций или заменив медленные операции более быстрыми. Также мы можем совместно работать над новым вариантом, если тебе интересен такой формат: ты пишешь код, а я анализирую его эффективность. В этом случае мы с тобой сможем раскрыть тему оптимизации последовательно, пост за постом. Какой из вариантов работы над этим заказом тебе наиболее интересен?
  10. @serafim Что-то я запутался. Это понятно. Но если вдобавок к этому мы разместим роботов так, чтобы каждый из них рубил в своём блоке, то о синхронизации вообще не надо будет думать. Каков смысл общего блока для совместной работы двух роботов, если у каждого есть свой инструмент для рубки? Какой способ хорош? Мой с тремя установщиками и одним рубщиком? Или тот, который предложил ты с двумя роботами?
  11. А в чём заключается преимущество именно такой схемы параллельной работы? Какой смысл размещать независимых роботов так, чтобы они имели общий блок для переработки руды, если проще сделать эти блоки отдельными для каждого робота? Это позволило бы вообще не задумываться о синхронизации роботов Мне было понятно, когда один робот рубил руду, а второй робот её устанавливал. Это позволяло повысить эффективность использования дорогого инструмента. Развивая эту идею, я использовал третьего и даже четвертого робота: три робота устанавливали руду в один общий блок, а четвёртый рубил руду в этом блоке. Но что даёт этот трюк с общим блоком в схеме на двух независимых роботах, когда каждый из них рубит своим инструментом?
  12. Улучшать программу можно бесконечно. Функционал растёт, увеличивается количество мест, где может возникнуть ошибка. Возникает куча вариантов их исправления. Например, что произойдёт, если в заряднике для инструмента рабочий слот окажется занятым? Игрок может что-то закинуть в него на зарядку. Значит, надо писать инструкцию, что зарядник должен быть свободен. Или робот должен временно вынимать этот инструмент, и вместо него класть на зарядку инструмент робота. Или просто выдавать ошибку и ждать. Но такую ситуацию в том или ином виде желательно предусмотреть. Код задержки начал так часто использоваться и копироваться, что пора выносить его в отдельную функцию. В текущем виде код разбухает, и есть шанс не заметить мелкую ошибку, допущенную при копировании. То же самое и со звуковыми сигналами: желательно разработать какую-то кодовую систему сигналов и вынести генерацию звука в отдельную функцию. Это упростит дальнейшую доработку программы, если она потребуется. И вообще, при большом разнообразии звуковых сигналов имеет смысл всё-таки ограничить их количество и добавить в робота видеокарту и монитор, чтобы выводить сообщения в более понятном виде. А звуковой сигнал можно использовать для привлечения внимания игрока. Впрочем, это моё субъективное отношение к проблеме оповещения, я не настаиваю именно на таком решении. Ещё я вижу проблему в этом участке кода: while r.durability() < lowcharge do Сейчас в случае, если автоматическая подзарядка не предусмотрена, робот просто ожидает, когда инструмент в его слоте зарядится. Сам собой от одного лишь ожидания он не зарядится, поэтому игрок в какой-то момент вручную извлечёт инструмент из робота для зарядки. А в это время на очередной итерации цикла программа прервётся ошибкой при попытке сравнения разных типов. Также желательно сбрасывать autocharge в false при отсутствии контроллера инвентаря или же обрабатывать ошибку в процессе работы, если, например, контроллер инвентаря съёмный. Или дожидаться его установки игроком. Тут, опять же, есть большой простор для обработки этой ситуации.
  13. Вроде бы правильно (если я ничего не упустил). Теперь программа стала даже чуть лучше оригинала. Но можно сделать ещё чуть лучше. Например, было бы полезным проверять успешность выгрузки предметов из слота и также впадать в спячку на время, пока игрок не освободит инвентарь. Пауза при неудачной выгрузке предметов не мене важна, чем при загрузке. Также есть три идеи для оптимизации: Здесь можно избавиться от вызова функций count: if r.suck(1, 64) then local rep = r.count(1) В документации сказано, что метод suck() возвращает значение типа boolean, но это не совсем так. В случае неудачи suck() вернёт false, а в случае успеха вернёт количество предметов. В каждой итерации цикла заново считывается размер инвентаря робота: while true do ... for i=1, r.inventorySize() do Это, конечно, экономит одну переменную, но память не экономит всё равно. Зато немного нагружает процесср. Считывание размера инвентаря в каждой итерации цикла имеет смысл только для роботов, оснащённых съёмными апгрейдами инвентаря. А эта строчка, по-моему, вообще лишняя r.select(1) Я не вижу особого смысла загружать предметы именно в первый слот. Может быть, если бы размер инвентаря робота превышал 16 слотов, то игроку было бы удобно визуально контролировать процесс работы программы. Но это, похоже, не тот случай. Только лишняя нагрузка на сервер.
  14. Да, так вернее. Но всё равно не надо спешить и тупо копировать код: local ws = computer.uptime() repeat computer.pullSignal(ws - computer.uptime()) until computer.uptime() >= ws Зачем в скопированном куске оставлять код цикла, зная, что тот выполнится ровно один раз? Зачем в скопированном куске оставлять код получения текущего времени, зная, что параметром функции computer.pullSignanl всегда будет ноль? Все эти лишние действия не бесплатны, они повышают нагрузку на игровой сервер.
  15. Можно сделать и так, если учесть, что при такой реализации пауза после переработки полного стака предметов будет равна не 5, а 8.2 секунды.
  16. Да, пауза стоит на тот случай, если кончится ресурсы, и для того, чтобы не создавать бесполезную нагрузку на сервер. Но в текущей реалзиации, прежде чем выполнится пауза, робот попытается взять блоки 255 раз. А это противоречит цели, ради которой в программу добавлена пауза. Это уже зависит от критериев критичности. Для чего именно не критичен сбой паузы? Для нагрузки на сервер? Так нагрузка обычно и складывается из таких мелочей, когда программа продолжает что-то делать, когда делать уже ничего не требуется. Да, задержка в 5 секунд всё равно сработает, рано или поздно. Тут я согласен. Я поспешил со своим категоричным заявлением. Был не прав. Переформулирую. Задержка почти никогда не выполнится сразу после рубки очередного стака блоков. В большинстве случаев задержка в 5 секунд выполнится лишь после 255 неудачных попыток получить блоки из сундука.
  17. Я ещё раз посмотрел код. Там после computer.pullSignal(0) следуют вызовы r.drop(0, 64). Соответственно, даже если произошло везение в предыдущей части кода, и очередь сигналов каким-то образом очистилась, то успешное выполнение robot.drop() снова поставит сигнал очистки слота робота в очередь событий. Итог: пауза не будет выполнена почти никогда.
  18. Каких прекрасных результатов можно достичь, если не спешить, и немного подумать! Но я предлагаю дополнительно поразмыслить. Казалось бы, в таком примитивном роботе попросту отсутствуют компоненты, которые бы могли генерировать сигналы. Тем не менее, генерируются сигналы при появлении или исчезновении предметов в инвентаре робота. При этом никто не забирает их из очереди событий. Теоретически, это могло бы происходить при вызове computer.pullSignal(0), но он выполняется только при неудачных попытках срубить блок, а значит, нечасто. К моменту вызова computer.pullSignal(5) очередь событий окажется, скорее всего, непустой. И попытка взять паузу окажется неудачной.
  19. За первую попытку, конечно же, лайк. Но всё же, не стоило так бездумно копировать код из стандартной библиотеки. Там же достаточно было несколько строк всего вытащить.
  20. Если дописать короткую инструкцию, как игроку обращаться с этой программой, и чего с ней делать нельзя, то можно и остановиться на этом. @demongts1998 протестируй эту версию. Она не идеальна, но вполне годная. Можно было бы немного снизить нагрузку на сервер, но на скорости заполнения реактора это существенным образом не отразится. Можно было бы сделать алгоритм более устойчивым к кривым рукам пользователей, но это потребует существенных усилий от программиста, проще написать инструкцию. Тем более, в условиях заказа не сказано, до какого состояния следует допиливать. Я считаю, допилено хорошо.
  21. Раз ценность роботов так повысилась, то, может быть, стоит использовать схему на одном роботе? Благодаря этом робот быстрее отработает свою цену. При желании можно установить четыре таких робота вокруг одного зарядника.
  22. Судя по тому, что я узнал в темах этого заказа и заказа про переработку руды, администраторы обсуждаемого сервера склоняют игроков именно к гринду. Что мы имеем: Ценность материалов на строительство реакторов и их компонентов настолько мала, а ценность энергии настолько велика, что игроки готовы строить по 324 реактора и обслуживать их даже без особой автоматизации. Мы слышим заявление от информированного человека о том, что причиной низкого TPS на сервере является большое количество реакторов. Но вместо снижения ценности энергии или дополнительно ограничения количества именно реакторов, администрация ввела крафт роботов за донат-валюту. Другое дело, что считают интересным сами игроки этого сервера. Поэтому вопросы к @demongts1998: Ты получаешь удовольствие от расстановки 324 реакторов вручную? Интересно ли тебе использовать робота, который сам расставит реакторы, или всё-таки ручная расстановка более предпочтительна? Целесообразна ли на этом сервере полная автоматизация, в которой роботы сами строят реакторы и обслуживают их? Или такая программа будет работать до ближайшего вайпа, и весь процесс снова скатится в тупой гринд, а к тому же ещё и роботы будут снова понерфлены? Какой сценарий ты считаешь наиболее вероятным? При низкой ценности материалов выгодны схемы на конденсаторах. Только они обеспечивают максимально плотное заполнение реактора топливом. Но именно эти схемы требуют активного перемещения реакторных компонентов между инвентарями и постоянного ремонта конденсаторов, что, конечно же, тоже вносит свой вклад в снижение TPS. Такие схемы обсуждались в заказе Программа "Очень много электричества". Это, конечно, не в 100 раз выше, а раз в 10. Но дальше могут возникать и другие препятствия из-за ограничения мода и аддонов: при определённых их сочетаниях производство энергии из MOX-топлива одним реактором может превышать возможности самого мощного потребителя, MFSU и самые лучшие кабели могут взрываться, или реактор может просто не выдать энергию свыше 16384 eu/t.
  23. Возможно, так и надо будет оставить, чтобы сделать программу программу более универсальной. Тогда имеет смысл использовать другое преимущество текущего решения. Т.к. мы сейчас всё равно заранее сканируем инвентарь, это даёт возможность сообщать игроку список недостающих компонентов ещё до начала заполнения реактора. И в те секунд 30, пока робот выкладывает компоненты, игрок может успеть сбегать за дополнительными, уже точно зная, каких именно компонентов не хватает.
  24. Я рассказывал на днях о методике измерений. За время выполнения getStackInInternalSlot (один тик) можно 1000 раз выполнить robot.count. При одиночном выполнении это, конечно, заметить трудно. Но при сканировании 64 пустых слотов робота будет заметно даже на глаз. Да, так сильно проще. Если не требуется заблаговременно уведомлять игрока об отсутствии ресурсов, то мы просто последовательно сканируем слоты робота и при обнаружении компонента проверяем, есть ли в реакторе слот, ожидающий именно этот компонент, и сразу переносим. Вместо таблицы содержимого инвентаря робота ведём таблицу ещё незаполненных слотов реактора. Завершив сканирование инвентаря робота и перенос, проверяем таблицу и выводим список недостающих компонентов. В сравнении с текущим вариантом для игрока не сильно что-то изменится. В целом, игрок будет получать уведомление о недостающих компонентах позже, но зато все уведомления сразу. Тут вариантов не особо много: либо тратить время на дополнительные запросы, либо аккуратно обрабатывать сигнал изменения слота, либо в инструкции пользователя прописывать запрет на некоторые манипуляции в процессе работы.
×
×
  • Создать...