ComST 15 Опубликовано: 31 января, 2016 (изменено) Здравствуйте, друзья мои! После создания моей первой программы для робота, у меня нет недостатка в пшенице. Но вот не задача. Ресурсов тоже нет. А так как я очень ленивая задница и ходить копать самому уже не охота - пусть это за меня делает робот! Сказано - сделано (через месяц). Представляю вашему вниманию программу для робота "Miner" ("Шахтер"). Робот, с минимальным железом на борту, с помощью данной программы может добывать ресурсы на заданном участке не упустив не единого алмазика (ну или уголька). Системные требования: Корпус 1-го уровня Процессор 1-го уровня 1 планка памяти 1,5-го уровня (это с запасом) HDD 1-го уровня Видеокарта -1го уровня Lua-BIOS Монитор 1-го уровня Клавиатура Улучшение "Инвентарь" Улучшение "Контейнер" 1-го уровня Геоанализатор Дополнения для обслуживания робота: Зарядное устройство Преобразователь энергии Источник энергии Сундук (1-2 шт.) Подготовка, установка, настройка и запуск. Робот устанавливается на поверхности (можно и в пещере), перед будущей шахтой справа. Под робота ставится сундук. Сбоку ставится зарядное устройство с источником питания. Например, я использую генератор из IC2 через АКБ, на угле, который добыл робот. Роботу необходимо выдать кирку и геоанализатор. Включаем робота и запускаем программу. Первое что робот спрашивает - это какая у шахты будет ширина. Т.е. это размер второстепенных тоннелей. Мин. значение - 2. Если ввести некорректное значение (<2) или не ввести вовсе, то робот примет значение по умолчанию равное 2. Второй вопрос - это длина. Т.е. размер главного тоннеля (от робота прямо по курсу). В связи со спецификой работы робота, введенное значение будет округлено до десятков в меньшую сторону, но не менее 10. Например, если ввести 34, то шахта будет 30 блоков в длину. Значение по умолчанию 10. Третий вопрос - глубина шахты. Отсчет ведется от места старта робота. Уровень на котором он стоит = 0, на один блок ниже = 1 и т.д. Например, если робот стоит на уровне 64, а бедрок находится на уровне 1 и вам надо дорыть до него, тогда задайте глубину 62. Так же, если ввести отрицательное значение или не ввести вовсе - значение будет 0. И последний вопрос - с какой глубины начать копать. Этот параметр удобен тем, что робот может начать копать с любой глубины, а не от точки старта. Например мне нужны алмазы. Я ставлю робота на поверхность (например высота 64), задаю ему глубину шахты = 59 (т.к. с глубины 5 начинается бедрок, а его робот грызть не умеет) и глубину для начала раскопок = 52 (основные залежи алмазов на глубине 12-5). После старта робот выкопает себе вертикальный тоннель, доберется до начала раскопок и начнет работать. Затем вернется тем же путем. После прохода одного уровня (одной высоты), робот возвращается на место старта, вываливает всё что нарыл вниз (надеюсь вы не забыли поставить под него сундук) и заряжается 20 сек. После этого идет на сл. глубину. Кстати, чуть не забыл. Робот добывает все блоки, кроме камня, булыжника, земли и гравия. Достоинства данной программы: Минимальные системные требования Добывает всё под чистую (кроме блэк-листа) Начинает копать с любого уровня Есть немного места для установки дополнительных апгрейдов Из-за встречи с мобом программа не собъется Добывает не только внутри шахты, но и ее внешний слой Недостатки: Если по каким-то причинам робот собьется (а вы его сможете найдете), то его не возможно вернуть в нужное русло. Только выключить, вернуть руками на старт и запустить заново с последней высоты. Необходимо следить, чтобы инструмент робота не сломался. Необходимо следить за уровнем энергии робота. Не может сам снабжать себя энергией. Заряжается на старте 20 сек. (может ему этого мало или много, в зависимости от размера шахты) Планы на будущее: Если робот собьется, то после повторного запуска сам начнет копать с глубины на которой закончил. Научить робота работать с буром из IC2 (зарядить, положить, взять) Ввести блек-лист задаваемый игроком. Робот будет сам заряжаться сколько ему необходимо. Если нужно вмешательство игрока, робот будет подавать сигнал. Разный цвет подсветки, в зависимости от выполняемой операции. Т.к. реализовать бОльшую самодостаточность робота с таким железом крайне сложно (хотя еще небольшой запас есть), далее будет программа для робота второго уровня. Просьбы: Как всегда жду здоровой критики, идей, предложений. Единственное ограничение - это должен быть робот 1-го уровня. Нужны советы в оптимизации кода. В коде много комментариев. Это для меня и др. новичков. Так что не пинать. Если вы знаете подобную программу - покажите ее, пожалуйста. Хочется сравнить. Зашел в соседнюю ветку, посмотрел, опупел. Моя прога еще только в зачатке. К админам сервера: придумайте, пожалуйста, что-нибудь с лагами на сервере. В сингле программа работает идеально. На сервере - пропускает команды, выполняет их по два раза. В общем жуть. Робот зарывается в такую опу, что приходится его часами искать. А! Собственно программа. http://pastebin.com/XkivBpat Изменено 1 февраля, 2016 пользователем ComST 6 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
qwertyMAN 1 722 Опубликовано: 31 января, 2016 К админам сервера: придумайте, пожалуйста, что-нибудь с лагами Слава грегу! 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 153 Опубликовано: 31 января, 2016 (изменено) Первое, за что глаз зацепился: function forward() --Движение робота на 1 блок вперед if r.forward() then -- Если робот может сделать шаг return true -- то хорошо :-) else -- Иначе... repeat r.swing() -- бъет по объекту впереди r.detect() -- проверяет остался ли объект until r.detect() == false -- Если нет.. r.forward() -- то шаг вперед end end1) r.detect() внутри repeat/until совершенно бесполезен. Зачем его вызывать, если результат не проверяется?2) Конструция r.detect() == false заменяется более компактной not r.detect() 3) Ошибка: r.forward() сразу за repeat/until не проверяется на успешное действие, поэтому могут быть сбои в движении. Конечно, перед этим была проверка, но между проверкой и действием могли произойти изменения: гравий осыпался, новый моб появился и т.д. 4) r.forward() в самом начале функции работает крайне неэффективно. Полгода назад я рассказывал об этом Артему (artem211), когда он писал свой геокопатель. Тогда, наверное, во всех найденных мною на этом форуме копалках имелась такая неэффективность. Безуспешная попытка r.forward() занимает столько же времени на выполнение, как и успешное движение. Поэтому продвижение сквозь сплошной массив породы по такому алгоритму замедляет робота почти в два раза. Есть два выхода. Самый простой и выбранный Артемом – делать взмах киркой до попытки движения. Почему-то на неудачный взмах кирки время не тратилось. Сейчас может быть иначе, или потом может измениться. Второй вариант более надежный в будущем, но и сложный – анализировать второй параметр, возвращаемый r.detect(). Изменено 31 января, 2016 пользователем eu_tomat 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 153 Опубликовано: 31 января, 2016 Первое что робот спрашивает - это какая у шахты будет ширина. Т.е. это размер второстепенных тоннелей. Мин. значение - 2. Если ввести некорректное значение (<2) или не ввести вовсе, то робот примет значение по умолчанию равное 2.До фразы про второстепенные тоннели следует объяснить, что это за тоннели такие, да и вообще хорошо бы кратко описать алгоритм разработки шахты. Тогда и программу будет легче читать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ComST Автор темы 15 Опубликовано: 31 января, 2016 (изменено) Первое, за что глаз зацепился: function forward() --Движение робота на 1 блок вперед if r.forward() then -- Если робот может сделать шаг return true -- то хорошо :-) else -- Иначе... repeat r.swing() -- бъет по объекту впереди r.detect() -- проверяет остался ли объект until r.detect() == false -- Если нет.. r.forward() -- то шаг вперед end end1) 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() действительно будет эффективнее. Спасибо за замечания! Исправлю. До фразы про второстепенные тоннели следует объяснить, что это за тоннели такие, да и вообще хорошо бы кратко описать алгоритм разработки шахты. Тогда и программу будет легче читать. Придется картинку нарисовать. У меня не хватает воображения словами это описать. Изменено 31 января, 2016 пользователем ComST Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 153 Опубликовано: 31 января, 2016 1) Результат проверяется в until r.detect() == false. Здесь он вызывается, а ниже проверяется. Или я чего-то не так понял? 2) Если я заменю, можно убрать "r.detect() -- проверяет остался ли объект"? 3) Логично. Надо подумать, как красиво исправить. 3) В смысле 4) Функция forward() служит исключительно для движения вперед, т.к. не всегда нужно копать перед собой. Если нужно что-то вскопать, это прописывается перед ее вызовом. Но раз там тратится столько времени, r.detect() действительно будет эффективнее. 1) r.detect() вызывается и в том и в другом случае, но результат проверяется лишь во втором, поэтому первый вызов бесполезен. 2) r.detect() внутри цикла не нужен в любом случае, а предложенная мною замена при проверке -- всего лишь более короткая форма записи, не влияющая на алгоритм работы. 4) Тут вопрос стоит так. Что будет быстрее? Сначала попытаться двигаться, а при неудаче сломать блок и еще раз попытаться, либо сначала не глядя сломать, а потом двигаться. В большинстве случаев путь робота-шахтера преграждают блоки. Поэтому даже если тратится время на неудачную добычу блока, в среднем по шахте это все равно будет быстрее, чем тратить время на неудачную попытку движения. P.S.: Поправлю свое сообщение, чтобы не путаться в двух пунктах с номером 3. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ComST Автор темы 15 Опубликовано: 31 января, 2016 (изменено) В большинстве случаев путь робота-шахтера преграждают блоки. Я провел эксперимент. Внес в код счетчик, сколько раз робот будет "врезаться" во что-то, а потом пытаться убрать это с пути. Итог получился забавный: за всю шахту он "споткнулся" только один раз и то об меня, когда я свалился к нему. Так что не вижу смысла махать тяпкой перед каждым шагом или за зря проверять есть ли впереди помеха. Если заранее знаешь, что впереди блок (например при рытье тоннеля), то у меня там стоит r.swing(), а потом уже forward(). А если робот возвращается на подзарядку - вря тле там ему что-то помешает. А если и появится какой-то моб, то время на его устранение уйдет меньше, чем проверять каждый раз впереди стоящий блок. Изменено 31 января, 2016 пользователем ComST Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ComST Автор темы 15 Опубликовано: 31 января, 2016 (изменено) 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 Не знаю, правильно ли вызывать функцию в этой же функции, но всё работает и теперь проверяется. Спасибо! Изменено 31 января, 2016 пользователем ComST Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 153 Опубликовано: 31 января, 2016 (изменено) Я провел эксперимент. Внес в код счетчик, сколько раз робот будет "врезаться" во что-то, а потом пытаться убрать это с пути. Итог получился забавный: за всю шахту он "споткнулся" только один раз и то об меня, когда я свалился к нему.Одно из двух: либо робот бродил в пустоте (повторно в той же шахте, или в пещере), либо счетчик что-то не то считает. Ищи ошибку. А я поднял свои записи шестимесячной давности, когда писал статью об эффективной копке, да ногу тогда сломал, и майнкрафт забросил. Сейчас перепроверил на свежей версии мода: при копке массива земли голой рукой ускорение в 1.5 раза, и в два – иридиевым буром. При проходе пустоты замедление на 10%. Не знаю, правильно ли вызывать функцию в этой же функции, но всё работает и теперь проверяется.Функцию из той же функции вызывать очень даже можно, и прием этот называется рекурсией. Иногда незаменимый и крайне эффективный, но в данном случае он дает только лишнее потребление памяти. А у тебя одна планка T-1.5. Код, конечно, рабочий, но он монструозный и тяжело воспринимается даже с комментариями, да и требует много места в памяти, а тут еще и рекурсия. Поэтому настоятельно советую: избавляйся от рекурсии. Готовое решение давать не буду, простые циклы ты освоил, а большего и не требуется. Изменено 31 января, 2016 пользователем eu_tomat 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ComST Автор темы 15 Опубликовано: 31 января, 2016 (изменено) Код, конечно, рабочий, но он монструозный и тяжело воспринимается даже с комментариями Вот оно! Надо мне правильно код научится писать. Так что: 1) Дополню статью алгоритмом разработки шахты и картиночками. 2) Уберу рекурсию. 3) Каким-нибудь образом постараюсь сделать код более читабельным. (Правда даже не представляю с чего начать и как это должно выглядеть) Изменено 31 января, 2016 пользователем ComST 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 153 Опубликовано: 31 января, 2016 И не забудь, что кроме r.forward() у тебя еще есть r.up() и r.down(). С ними надо работать аналогично, чтобы робот не сбивался с пути. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Dogge1 0 Опубликовано: 25 июля, 2016 У меня есть глупый вопрос ... А как программу запустить ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
TraerTaer 39 Опубликовано: 25 июля, 2016 function rforward() if not r.forward() then r.swing() end end А такое не катит? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
unknown 23 Опубликовано: 15 августа, 2016 (изменено) ... А такое не катит? Ну, если автор желает сам решить проблему, то не будем ему мешать. Но, @@TraerTaer, ты чууть-чуть ошибаешься. function forward() while not r.forward() then r.swing() end end Вот так, надеюсь, прокатит. Хотя мы, опять же, не принимаем в расчет время, затрачиваемое разными действиями робота, а это важно! Изменено 15 августа, 2016 пользователем unknown Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах