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

Totoro Recursive Miner

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

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

Программа копает узкий длинный тоннель. Каждую найденную жилу руды, робот выбирает полностью, используя специальный рекурсивный алгоритм. После того, как жила выработана полностью, робот возвращается обратно, и продолжает копать тоннель.
Робот использует для подзарядки добытый уголь. Когда инвентарь переполняется - он ставит Ender Chest и складывает добытое в него. Затем забирает его и двигается дальше.

2014-09-11_23.49.58.png

Использование
Totoro Recursive Miner:
http://pastebin.com/sN8hJBFH (версия 0.2)

http://pastebin.com/L21VMm7S (версия 0.5H, последняя на текущий момент. Обновленные инструкции по установке и использованию тут)

Робот должен иметь чанклодер, генератор и хотя бы один (лучше два или три) апгрейд на инвентарь. Также желательно иметь большой объем оперативной памяти.

В начале программы записаны две константы:

INV_SIZE = 24
TECH_SLOTS = 8

INV_SIZE - общее количество слотов в инвентаре
TECH_SLOTS - технические слоты (от начала инвентаря)

В технические слоты кладутся образцы пустой породы, которую не надо добывать. Слотов 8, так как GregTech добавляет цветной гранит, а RailCraft - abyssal stone. Обычно в первых слотах лежит: камень, земля, гравий, булыжник, красный гранит, черный гранит, abyssal stone.
В последний, восьмой слот, кладется Ender Chest.

Программа принимает два параметра:


mine [len] [height]

len - длина тоннеля (по умолчанию - 10)
height - высота (по умолчанию - 4)

P.S. Бета версия. =) Может сбиваться гравием, может закончить работу на дне лавового озера. Если не положите образец земли с травой, а робот будет копать близко к поверхности - есть риск что он поедет обдирать дерн со всего "майнерс"-мира.

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

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


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

Интересненько! Можешь вставить счетчики подсчета эффективности?

Например эти счетчики?

Количество ходов(перемещений за сессию) - count_run

Количество выкопанного(всего) - count_dig

Количество выкопанного(полезной руды) - useful_dig

Время, потраченное на сессию и т.п.

 

Посчитать бы соотношения все эти. Насколько выгоднее или не выгоднее по сравнению с бурением в объеме на заданном диапазоне высот через два слоя на третий и проверка верхнего и нижнего блока с прерыванием, если найдено совпадение с "мусорными" слотами. Таких вроде жил огромных у нас нет. Разве что уголь залегает большими пластами (скоплениями) Эмиральдики вообще по одному кусочку лежат. Но задумка интересная. Надо будет полигончик тестовый сделать роботу и посмотреть, как он жилу вырабатывает. Когда-то давно на КК видел такой(или похожий) алгоритм, но там черепашка дергалась туда сюда и очень много телодвижений делала лишних, пока выкопала жилу из 4-5 блоков руды.

 

П.С. Читерные способы вроде зачарованных буров 3x3, динамитных шашек в связке с магнитом и прочее пока не рассматриваем.

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


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

Сделал тестовый "заезд" с Супер Киркой. Задал тоннель 100х10. Робот выкопал 1387 блоков, из них - 451 блок полезный. Совершил 1411 движений.

 

Я тут подумал - моя программа делает тоннель в вертикальной плоскости. А что если перенести этот процесс в горизонтальную?

При это должна увеличиться скорость - отпадают лишние повороты.

 

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

Жилу мой алгоритм довольно шустро выбирает.

 

Где будет больше руды - в кубе или в вытянутом горизонтальном слое такого же объема?

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


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

Тоторо, хорошая идея и реализация. Понравилась простота кода. Даже нет строчек больше 30-40 символов.

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


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

Тоторо, хорошая идея и реализация. Понравилась простота кода. Даже нет строчек больше 30-40 символов.

Спасибо =)

 

Сделал версию с горизонтальным "срезом". Программа стала проще и короче (теперь умещается в 256 строк - как раз один буфер обмена OC). Робот работает быстрее, при той же эффективности. Правда "шахта" выглядит немного странно :)

 

Исходный код:

http://pastebin.com/NQe6P6NR

 

Робота необходимо ставить в правый угол предполагаемого тоннеля, передней стороной - на левый угол. (Сэкономил на навигации =))

Остальное (образцы пустой породы, ender chest) - так же как и в первом варианте.

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


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

Totoro, прокомментируйте часть кода, которая отвечает непосредственно за выкапывание жилы, пожалуйста - я плохо знаком с OC и не все понятно.

 

Я хочу сделать выкапывалку жилы для CC, но получается как-то очень сложно:

 

1. На входе читаем пределы размерности жилы (для простоты, пусть будет одно число N - половина длины ребра куба за пределы которого не следует выходить, половина - потому что жила может находиться не только перед нами) и номера слотов под блеклист.

2. Инициализируем нулями массив x * y * z блоков, где x = y = z = N*2; считаем, что 0 - неизвестный блок, 1 - blacklisted блок, 2 - passable (проходимый) блок (воздух или жидкость), 3 - mineable (т.е. detectable, не-blacklisted и non-passable блок);

3. Считаем, что находимся в 0,0,0.

4. Заводим стек mineables для mineable блоков.

5. Делаем detect(), зате compare() с blacklisted слотами всех блоков вокруг, записываем результаты в массив, координаты mineable блоков заносим в стек.

6. Выкапываем первый блок из стека, перемещаемся на его место.

7. Повторяем п. 5-7 до тех пор, пока в стеке остается хотя бы одна запись.

8. Возвращаемся в 0,0,0.

 

Из сложных сложностей здесь - нужен pathfinding чтобы возвращаться к несмежным mineable блокам если жила ветвится. Хотя, наверное, можно выбросить карту и заносить в стек mineable блоки и свои перемещения, чтобы потом просто двигаться в обратном направлении.

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


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

У меня сделано очень похоже на это.

 

Я делал так:

1) Завел переменную MAX, куда записал максимальный размер стороны куба, который может содержать жилу. У меня это 1024 блока. Размер просто нереальный, даже для черного гранита =)

2) При обнаружении чего-то интересного - вызывается функция go(). Она записывает, куда смотрел мордой робот, чтобы вернуть его в правильное положение, когда он закончит выкапывать жилу. Затем объявляется пустая таблица lode (жила). Элемент с любым индексом в новой таблице будет всегда nil. Этим и пользуюсь. Элемент nil означает, что этот блок робот еще не исследовал. И наконец - вызов рекурсивной функции mine. Ей передается сторона, с которой надо начать.

3) Первая часть mine: функция получила параметр - сторону, которую надо копать. Она ее копает (добавлены циклы, на случай гравия. И все равно ведь где-то сбивается :confused:)

4) Вторая часть: команда lode[loc.x*MAX*MAX + loc.y*MAX + loc.z] = true

Чтобы не заморачиваться с 3D массивом, я генерирую на основе трех координат уникальный индекс. И делаю запись в таблице - true: значит текущий блок пройден.

5) Третья часть. Робот начинает проверять соседние блоки. Он вычисляет их координаты (прибавляет или отнимает от нужной оси по 1) и смотрит массив lode. Если в ячейке - nil, значит робот еще не был в этом блоке, и не проверял его.

Если там пустая порода, робот записывает false в таблицу и проверяет следующий блок. Если там руда - вызывает функцию mine с параметром - стороной где обнаружена руда. Получается - функция mine вызывает сама себя. (Рекурсия. Откуда название программы =))

6) Завершающая часть. Робот вспоминает, какую сторону ему передали в начале, и делает движение обратно. Если он копал вниз - он поднимается. Если копал вперед - разворачиваеся назад и делает шаг.

 

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

 

Там к работе возвращается функция go(), которая поворачивает робот в исходное положение.

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


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

Таким образом, вложенные вызовы mine завершаются поочереди, начиная с самого последнего, и получается, что робот возвращается точно по своим следам в исходную точку.Там к работе возвращается функция go(), которая поворачивает робот в исходное положение.

Круто! То есть, как я понял, робот проверяет с каждой новой выкопанной позиции все 5 новых направлений, и если там ничего нет, возвращается на предыдущую позицию - и так, пока не завершит все цепочки проверок по всем возможным ветвлениям и направлениям жилы? А дальше едет по основному направлению копания. Единственное, возможно, что некоторые не полезные блоки проверяются повторно с разных сторон или это учитывается в массиве?

 

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

 

Кстати на новом сервере планирую с удорожанием и усложнением рецептов роботов апнуть их технические характеристики, а именно уменьшить задержки при перемещениях и копании. Скорее всего, использовать роботов будет выгоднее при бурении, чем черепах, так как выход руды за определенное время по идее станет больше. Плюс сундук, чанклоадер, навигация, расширение инвентаря(кстати, какой сейчас максимально возможный инвентарь у робота, 24 слота?) Черепах можно будет использовать на начальной стадии развития.

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


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

Круто! То есть, как я понял, робот проверяет с каждой новой выкопанной позиции все 5 новых направлений, и если там ничего нет, возвращается на предыдущую позицию - и так, пока не завершит все цепочки проверок по всем возможным ветвлениям и направлениям жилы? А дальше едет по основному направлению копания. Единственное, возможно, что некоторые не полезные блоки проверяются повторно с разных сторон или это учитывается в массиве?

Именно так.

А один и тот же блок он не проверяет detect()'ом дважды. Если от пометил блок как false - пустая руда, то, когда он подойдет к нему с другой стороны, и начнет проверку сначала по массиву - блок, отмеченный false (пустая порода) или true (уже выкопан), отсеется сразу.

Потому робот не будет тратить время и поворачиваться к блоку, который он уже обследовал. Он повернется к первому неизвестному (который в таблицу не занесен - nil).

 

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

На обычном не пробовал, т.к. я обкатывал программу у нас на сервере. Он возит с собой сундук из Ender Storage, настроенный на одну цветовую комбинацию с другим сундуком, из которого выкачивает ресурсы ME Import Bus.

Что касается лавы - он у меня сейчас остается в точке, пригодной для того, чтобы сразу продолжить копать. А если там (случайно) лавовое озеро, его это естественно не смущает. Локальные координаты от сохраняет (блок NAVIGATION). В принципе - можно сделать чтобы он проверял окрестности на жидкость. А если вокруг лава (или вода) - пятился бы назад до сухого места =)

 

...Плюс сундук, чанклоадер, навигация, расширение инвентаря(кстати, какой сейчас максимально возможный инвентарь у робота, 24 слота?) Черепах можно будет использовать на начальной стадии развития.

Каждый апгрейд на инвентарь - плюс 16 ячеек. Мой робот-дровосек имеет четыре апгрейда - инвентарь на 64 ячейки (хотя ему столько не нужно =))

В коде 24 я написал, чтобы оставить небольшой буфер, на случай, если проверку пройдет слишком поздно и часть добытого начнет высыпаться. Вообще у робота-шахтера - 32 ячейки.

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


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

Потому робот не будет тратить время и поворачиваться к блоку, который он уже обследовал. Он повернется к первому неизвестному (который в таблицу не занесен - nil)....

 

Супер!

 

...На обычном не пробовал, т.к. я обкатывал программу у нас на сервере. Он возит с собой сундук из Ender Storage, настроенный на одну...

Ясно, просто я сторонник того, чтобы по максимуму использовать только возможности самого мода + ваниль. Ну раз есть, то есть. Просто не на всех серверах стоят ЭндерСтореджи и т.п., а точнее почти нигде их нет, например на новый сервер я его не ставил.

 

...Мой робот-дровосек имеет четыре апгрейда - инвентарь на 64 ячейки (хотя ему столько не нужно =))...

Ой ёёёё! Видно я отстал от жизни. Да-а-а.... Черепахи - это прошлый век. По сравнению с роботом черепаха нервно курит в тамбуре. А возврат робота по окончании работы хотелось бы видеть. Как его потом искать в океанах лавы и потемках пещер.

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


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

... Просто не на всех серверах стоят ЭндерСтореджи и т.п., а точнее почти нигде их нет, например на новый сервер я его не ставил.

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

 

Обновил программу для горизонтального копания:

http://pastebin.com/NQe6P6NR

 

Теперь формат вызова выглядит так:

mine <length> [width] [return]

 

Где return принимает значение true или false.

Если true - робот после работы возвращается в исходную точку.

По умолчнию - не возвращается.

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


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

А какой минимальный объем оперативки нужен роботу для запуска (и рекомендуемый объем тоже)

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


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

А какой минимальный объем оперативки нужен роботу для запуска (и рекомендуемый объем тоже)

Проверять надо, посчитать нельзя. Я ставлю в роботы-копалки по два ОЗУ уровня 2.5. Этого мне вполне хватает.

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


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

А какой минимальный объем оперативки нужен роботу для запуска (и рекомендуемый объем тоже)

У меня тоже стоят две планки по 2.5. Их вполне хватило, когда робот по ошибке начал выкапывать пласт черного гранита. И прежде, чем я его поймал, он уже выкопал изрядно.:)

А точного измерения я еще не проводил.

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


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

Новая версия Horizontal Recursive Miner 0.41

http://pastebin.com/NQe6P6NR

 

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

По умолчанию этот режим отключен.

Для того, чтобы включить его, установите константу VANILLA_CHEST в начале программы в значение true. А в последний тех.слот (по дефолту - 8-ой) положите стек обычных сундуков вместо эндер-сундука.

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


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

Сегодня посчастливилось наблюдать роботу этой программы. Totoro со своим роботом занимались добычей полезных ископаемых  :)

 

Могу сказать только одно. Карьер из БК нервно курит в тамбуре. Робот исправно, как в аптеке, аккуратно и четко вырабатывал всю руду в жилах, которая залегала на его пути, не пропуская ни кусочка. За собой оставлял полные сундучки, сам заправлялся, когда садилась батарейка от твердотопливного генератора, и очень уверенно и слаженно выполнял всю работу. Смотреть за работой программы - одно удовольствие.

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


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

Вот бы еще кто научил пользоваться этими роботами...

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


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

Вот бы еще кто научил пользоваться этими роботами...

Верно, верно. Мы ставили на C&S у Гравити, кажется, этот майнер, так он поднялся, развернулся, покрутился, а затем крашнулся :D

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


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

После того как робот заполняется, он ставит ванильный сундук, НО! он ставит его в породу(над сундуком есть блоки) и предметы просто выкидываются, и удаляются сервером через 30 сек...как можно решить эту проблему?

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


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

Функцию unload приведи к виду:
 

  1. function unload()
  2.   -- place ender chest
  3.   robot.select(chest_slot)
  4.   robot.swingDown()
  5.   if robot.placeDown() then
  6.     -- put items
  7.     for i=empty_slot, INV_SIZE do
  8.       robot.select(i)
  9.       while robot.dropDown() do end
  10.     end
  11.  
  12.     -- grab ender chest
  13.     if not VANILLA_CHEST then
  14.       robot.select(chest_slot)
  15.       robot.swingDown()
  16.     end
  17.   end
  18. end
    (тоесть добавь где нужно
    Down чтобы прокопал под сундук вниз и вниз его ставил)
Изменено пользователем KelLiN

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


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

Присоединяйтесь к обсуждению

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

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


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