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

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

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

Doob

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

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

  • Посещение

  • Дней в лидерах

    65

Последний раз Doob выиграл 18 февраля

Публикации Doob были самыми популярными!

Репутация

1 456 Очень хороший

8 подписчиков

О Doob

Информация

  • Пол
    Не определился

Посетители профиля

944 просмотра профиля
  1. Doob

    Робот с геосканером. Часть #7 [способы добычи]

    Да, хорошо, штраф сделать не просто разницей между верхним Y и текущим. А умножением, относительно всей доступной высоты. Так и сделаю. Повороты можно даже не штрафовать, а делать анализ, на этапе поиска цели.
  2. Для настройки работы программы, надо узнать плотность добываемых блоков и плотность мусора, чтобы сделать предварительный фильтр на этапе сканирования. Плотность одной руды в разных модах отличается, но она близка к ванильной т. к. механика работы инструментов одна. Сделал шпаргалку с информацией о плотностях из разных модов. Плотность, уровень инструмента, название. Minecraft 3 2 Алмазная руда 3 2 Изумрудная руда 3 2 Золотая руда 3 2 Красная руда 3 1 Железная руда 3 1 Лазуритовая руда 3 0 Угольная руда 3 0 Кварцевая руда 0.3 -1 Светокамень -1 -1 Бедрок 50 3 Обсидиан 3 -1 Эндерняк 2.5 0 Сундук 2 0 Булыжник 2 -1 Адский кирпич 2 0 Доски 1.5 0 Камень 1.5 -1 Каменный кирпич 1.25 -1 Терракота 0.8 0 Песчаник 0.6 0 Трава 0.6 0 Гравий 0.6 0 Глина 0.5 0 Земля 0.5 0 Песок 0.4 0 Адский камень 0.5 0 Песок душ -------------------------------------------- IC2 4 2 Урановая руда 3 1 Медная руда 3 1 Оловянная руда 2 1 Свинцовая руда -------------------------------------------- AE2 50 3 Небесный камень 50 0 Сундук из небесного камня 3 0 Кварцевая руда -------------------------------------------- Mekanism 3 -1 Осмиевая руда 3 -1 Медная руда 3 -1 Оловянная руда -------------------------------------------- Forestry 3 1 Апатитовая руда 3 1 Медная руда 3 1 Оловянная руда -------------------------------------------- TConstruct 10 4 Кобальтовая руда 10 4 Ардитовая руда -------------------------------------------- ThermalFoundation 3 1 Медная руда 3 1 Оловянная руда 3 2 Серебряная руда 3 2 Свинцовая руда 3 1 Алюминиевая руда 3 2 Никелевая руда 3 3 Платиновая руда 3 3 Иридиевая руда 3 3 Мифриловая руда -------------------------------------------- Galacticraft 6 1 Алюминиевая руда 5 1 Оловянная руда 5 1 Медная руда 3 2 Кремниевая руда Moon 5 1 Медная руда 5 1 Оловянная руда 5 -1 Сапфировая руда 3 1 Сырная руда 1.5 0 Лунный камень 0.5 0 Лунный грунт 0.5 -1 Лунный дерн Mars 2.2 3 Деш руда 2.2 1 Железная руда 2.2 1 Оловянная руда 2.2 1 Медная руда 2.2 0 Булыжник 2.2 0 Реголит Asteroids 3 2 Алюминиевая руда 3 3 Ильменитовая руда 3 2 Железная руда 3 0 Камень Venus 5 -1 Алюминиевая руда 5 -1 Медная руда 5 -1 Свинцовая руда 5 -1 Кварцевая руда 5 -1 Кремниевая руда 5 -1 Оловянная руда 5 -1 Солнечная пыль 2.2 1 Магма 2.2 1 Пемза 1.5 1 Твердый камень 0.9 1 Мягкий камень 0.9 -1 Выжженный камень
  3. Doob

    Робот с геосканером. Часть #7 [способы добычи]

    Предпочтения игрока тут не учесть, руды все одной плотности (ic2 свинец это недоразумение, а не руда). Послойная обработка не выгодна тем, что робот нарезает круги, когда в паре слоев от него есть руда. Сплошную поддерживают оба алгоритма -- пока не будет добыт весь кластер, робот не уйдет, но послойный оставит недоступный слой на потом. На стандартных генерациях ванилы, IC2, AE2 (тестировались отдельно) свободный обход существенно превосходит послойный (4 чанка, высота 64). Поэтому, статистика говорит в сторону этого подхода, а что админ накрутит генерацию - проблема индейцев. Изначально, я планировать сделать гибрид из этих двух алгоритмов - робот свободно выбирает цель, но получает огромный штраф на ход по вертикали +Y. Добыча велась бы максимально оптимально и робот заканчивал чанк наверху, откуда короче путь к старту следующего чанка. На стенде подобрал расположение руд, чтобы оно было похоже на реальную генерацию и оба алгоритма были бы в одних условиях (руда в каждом слое, свободный пробег 1600 блоков) Меня больше интересуют советы по оптимизации упаковщика, потому-что на каждый сундук робот тратит около 30 секунд. В прошлой версии скорость была фантастической, но хак, который я использовал убрали после какой-то обновы.
  4. Странно, у меня личные сообщения нормально обрабатываются. Флаг для логирования можно тоже сунуть в конфиг. Конфиг следует сделать в виде lua-таблицы - быстрей и меньше кода. Изначально все задумывалось как программный модем между компами. Логин для NickServ и прочие изощрения поверх стандарта, пользователь должен был организовывать в своей программе. imodem это всего-лишь интерфейс, совместимый с OpenOS. Хотя, да не сделал пинг в сторону сервера, каюсь.
  5. Все-таки добывать руду слоями дольше, чем свободным обходом всех доступных блоков. На тестовом стенде свободный - 2 минуты 50 секунд, послойный - 3 минуты 9 секунд. Тут очень сильно напрашивается дополнительная эвристика на сокращение поворотов и прямых одноблочных ходов. И упаковку запускать только при нужде.
  6. Doob

    Робот с геосканером. Часть #1 [движения]

    Экономия скорости не большая, по сравнению с потреблением памяти. В прошлой версии, робот сканировал и добывал слой за слоем, меток было мало. В этой версии такой подход не очень подходит, эксперименты показывают, что искать ближайший блок по всему чанку выгодней, чем послойно, даже если добывать слой 3 блока.
  7. Добытые ресурсы надобно рассортировать. Для этого дела задействуем контроллер инвентаря. Надобно пройти по всем слотам, получить информацию о содержимом и сравнить название со списком ненужных предметов (который предварительно составим), при совпадении опустошать. Но это не вся функция. У нас есть еще верстак, который может помочь, очень сильно ужать, некоторые ресурсы (уголь, редстоун, алмазы, изумруды, лазурит). Верстак занимает в инвентаре 9 слотов, еще 1 слот добавим на результат, если не все влезет в блок. Поэтому, пока робот ищет мусор, пусть считает пустые слоты, для верстака. В начале уберем блоки сверху и снизу, чтобы случайно не перемешать мусор с излишками добра. для удобоваримости сократил некоторые имена: inventory - размер инвентаря, получим в начале работы программы, controller - контроллер инвентаря, tails - список названий лишних предметов (без префикса "minecraft:", можно добавлять названия из любого мода) robot.swing(0) -- освободить место для мусора robot.swing(1) -- освободить место для буфера ------- сброс мусора ------- local empty = 0 -- создать счетчик пустых слотов for slot = 1, inventory do -- пройти по слотам инвентаря local item = controller.getStackInInternalSlot(slot) -- получить информацию о предмете if item then -- если есть предмет for name = 1, #tails do -- пройти по таблице хвостов if item.name:gsub('%g+:', '') == tails[name] then -- проверить на совпадение robot.select(slot) -- выбрать слот robot.drop(0) -- выбросить к отходам empty = empty + 1 -- обновить счетчик break -- прервать цикл сравнения end end else empty = empty + 1 -- обновить счетчик end end Далее следует проверить и выкинуть наверх предметы, которые будут мешать при крафте. Подсчитанные пустые слоты отнимем от требуемого количества для крафта, пройдем по инвентарю уберем их. -- упаковка предметов в блоки -- if crafting then -- если есть верстак -- перенос лишних предметов в буфер -- if empty < 10 then -- если пустых слотов меньше 10 empty = 10-empty -- увеличить количество пустых слотов для обратного отсчета for slot = 1, inventory do -- просканировать инвентарь if robot.count(slot) > 0 then -- если слот не пуст robot.select(slot) -- выбрать слот robot.drop(1) -- выбросить в буфер empty = empty - 1 -- обновить счетчик end if empty == 0 then -- если место освободилось break -- прервать цикл end end end Предварительно создадим таблицу fragments, в которой будут храниться названия предметов, которые можно сложить в блоки. Теперь создадим таблицу, в которой будут счетчики для каждого типа фрагментов. Пройдем по инвентарю, получим информацию о слоте, сравним, прибавим - все как в первом цикле, можно было бы даже их объединить, но на предыдущем шаге мы выкинули какие-то предметы. Чтобы узнать какие именно - придется городить еще один цикл, оставим как есть. -- подсчет предметов доступных для упаковки -- local available = {} -- создать таблицу счетчиков for slot = 1, inventory do -- пройти по слотам инвентаря local item = controller.getStackInInternalSlot(slot) -- получить информацию о предмете if item then -- если есть предмет for n = 1, #fragments do -- пройти по списку названий фрагментов if item.name:gsub('%g+:', '') == fragments[n] then -- сравнить по имени if available[n] then -- если есть подобные фрагменты available[n] = available[n] + item.size -- обновить else -- иначе available[n] = item.size -- создать end break end end end end Наконец-то можно крафтить. Хотя, нет. Надо расчистить слоты верстака, чтобы в него сложить рецепт. Будем перебирать слоты от 1 до 9, но в роботе верстак занимает слоты с другими номерами, а именно 1 2 3 5 6 7 9 10 11, можно было бы составить условие от 1 до 11, с исключением целых по модулю 4. Сделаем проще - номера слотов занесем в таблицу "workbench", которая будет служить списком ссылок с системы 1-9 на 1-11. Вынесем ее подальше, чтобы она не создавалась при каждом запуске. В цикле проверяем количество предметов в слоте, если оно не нулевое - ищем в инвентаре пустой слот, исключая слоты верстака. Переносим предметы в найденный слот. Если перенести не удалось - что-то попало в верстак после крафта. Забираем предметы из буфера и завершаем функцию, возвращая true, что будет сообщать о перегрузе и времени выдвигаться домой. for c_slot = 1, 9 do -- цикл чистки зоны верстака if robot.count(workbench[c_slot]) > 0 then -- если слот не пуст robot.select(workbench[c_slot]) -- выбрать слот верстака for slot = 4, inventory do -- обойти весь инвентарь, кроме рабочей зоны if robot.count(slot) == 0 and (slot == 4 or slot == 8 or slot > 11) then -- если есть свободный robot.transferTo(slot) -- освободить слот break -- выйти из цикла end end if robot.count() > 0 then -- проверить на перегрузку robot.suck(1) -- забрать из буфера return true -- остановить упаковку end end end Верстак расчищен, пора заняться упаковкой. Перебираем слоты инвентаря, исключая верстак, сравниваем названия со списком. При совпадении, делим содержимое на 9, заполняем верстак И крафтим блок. ------- основной цикл крафта ------- for slot = 4, inventory do -- цикл поиска фрагментов local item = controller.getStackInInternalSlot(slot) -- получить информацию о предмете if item and (slot == 4 or slot == 8 or slot > 11) then -- если есть предмет вне рабочей зоны if item.name:gsub('%g+:', '') == fragments[i] then -- сравнить по названию фрагмента robot.select(slot) -- при совпадении выбрать слот for n = 1, 9 do -- цикл заполнения рабочей зоны robot.transferTo(workbench[n], item.size/9) -- разделить текущий стак на 9 частей и перенести в верстак end if robot.count(1) == 64 then -- сброс при заполнении верстака break end end end end crafting.craft() -- создание блока Можно заметить fragments, откуда i? Об этом позже. После крафта могли остаться какие-то остатки, если не все слоты поделились на 9. Проверяем содержимое в слотах, если предметов меньше 64 - перебираем слоты после текущего и сравниваем, при совпадении содержимого пробуем перенести. При опустошении текущего слота - прерываем перебор со сравнением. -- цикл сортировки остатков for A = 1, inventory do -- основной проход local size = robot.count(A) -- получить количество предметов if size > 0 and size < 64 then -- если слот не пуст и не полон robot.select(A) -- выбрать слот for B = A+1, inventory do -- проход сравнения if robot.compareTo(B) then -- если предметы одинаковые robot.transferTo(B, 64-robot.count(B)) -- перенести до заполнения end if robot.count() == 0 then -- если слот освободился break -- прервать сравнение end end end end Последние три цикла заворачиваем в такую конструкцию: for i = 1, #fragments do -- перебор всех названий if available[i] then -- если в инвентаре такой есть for j = 1, math.ceil(available[i]/576) do -- разделить результат на стаки ... end end end Первый цикл перебирает названия фрагментов. Условный оператор проверяет наличие такого типа в инвентаре. Внутренний цикл повторяет чистку, крафт и сортировку, если в результате будет больше стака блоков. Новые используемые переменные: local tails = {'cobblestone','dirt','gravel','sand','stained_hardened_clay','sandstone','stone','grass','end_stone','hardened_clay','mossy_cobblestone','planks','fence','torch','nether_brick','nether_brick_fence','nether_brick_stairs','netherrack','soul_sand'} local workbench = {1,2,3,5,6,7,9,10,11} local fragments = {'redstone','coal','dye','diamond','emerald'} local controller = add_component('inventory_controller') local crafting = add_component('crafting') local inventory = robot.inventorySize() Полный текст функции, с более рациональным вызовом robot.count(): local function sorter() -- сортировка лута robot.swing(0) -- освободить место для мусора robot.swing(1) -- освободить место для буфера ------- сброс мусора ------- local empty = 0 -- создать счетчик пустых слотов for slot = 1, inventory do -- пройти по слотам инвентаря local item = controller.getStackInInternalSlot(slot) -- получить информацию о предмете if item then -- если есть предмет for name = 1, #tails do -- пройти по таблице хвостов if item.name:gsub('%g+:', '') == tails[name] then -- проверить на совпадение robot.select(slot) -- выбрать слот robot.drop(0) -- выбросить к отходам empty = empty + 1 -- обновить счетчик break -- прервать цикл сравнения end end else empty = empty + 1 -- обновить счетчик end end -- упаковка предметов в блоки -- if crafting and empty < 12 then -- если есть верстак и переполнение -- перенос лишних предметов в буфер -- if empty < 10 then -- если пустых слотов меньше 10 empty = 10-empty -- увеличить количество пустых слотов для обратного отсчета for slot = 1, inventory do -- просканировать инвентарь if robot.count(slot) > 0 then -- если слот не пуст robot.select(slot) -- выбрать слот robot.drop(1) -- выбросить в буфер empty = empty - 1 -- обновить счетчик end if empty == 0 then -- если место освободилось break -- прервать цикл end end end -- подсчет предметов доступных для упаковки -- local available = {} -- создать таблицу счетчиков for slot = 1, inventory do -- пройти по слотам инвентаря local item = controller.getStackInInternalSlot(slot) -- получить информацию о предмете if item then -- если есть предмет for n = 1, #fragments do -- пройти по списку названий фрагментов if item.name:gsub('%g+:', '') == fragments[n] then -- сравнить по имени if available[n] then -- если есть подобные фрагменты available[n] = available[n] + item.size -- обновить else -- иначе available[n] = item.size -- создать end break end end end end ------- основной цикл крафта ------- for i = 1, #fragments do -- перебор всех названий if available[i] then -- если в инвентаре такой есть for j = 1, math.ceil(available[i]/576) do -- разделить результат на стаки for c_slot = 1, 9 do -- цикл чистки зоны верстака if robot.count(workbench[c_slot]) > 0 then -- если слот не пуст for slot = 4, inventory do -- обойти весь инвентарь, кроме рабочей зоны if robot.count(slot) == 0 and (slot == 4 or slot == 8 or slot > 11) then -- если есть свободный robot.select(workbench[c_slot]) -- выбрать слот верстака robot.transferTo(slot) -- освободить слот break -- выйти из цикла end end if robot.count() > 0 then -- проверить на перегрузку robot.suck(1) -- забрать из буфера return true -- остановить упаковку end end end ------- основной цикл крафта ------- for slot = 4, inventory do -- цикл поиска фрагментов local item = controller.getStackInInternalSlot(slot) -- получить информацию о предмете if item and (slot == 4 or slot == 8 or slot > 11) then -- если есть предмет вне рабочей зоны if item.name:gsub('%g+:', '') == fragments[i] then -- сравнить по названию фрагмента robot.select(slot) -- при совпадении выбрать слот for n = 1, 9 do -- цикл заполнения рабочей зоны robot.transferTo(workbench[n], item.size/9) -- разделить текущий стак на 9 частей и перенести в верстак end if robot.count(1) == 64 then -- сброс при заполнении верстака break end end end end crafting.craft() -- создание блока -- цикл сортировки остатков for A = 1, inventory do -- основной проход local size = robot.count(A) -- получить количество предметов if size > 0 and size < 64 then -- если слот не пуст и не полон for B = A+1, inventory do -- проход сравнения if robot.compareTo(B) then -- если предметы одинаковые robot.select(A) -- выбрать слот robot.transferTo(B, 64-robot.count(B)) -- перенести до заполнения end if robot.count() == 0 then -- если слот освободился break -- прервать сравнение end end end end end end end end robot.suck(1) --- забрать предметы из буфера end
  8. Doob

    Робот с геосканером. Часть #5 [тонкий расчет]

    По-другому никак. Естественно, все условия надо будет проверять при запуске и пинать пользователя, чтобы он соблюдал инструкцию.
  9. Doob

    Робот с геосканером. Часть #5 [тонкий расчет]

    Как это неизвестно? Первые три строчки как раз про это самое. Получаем заряд батарей computer.energy() Делаем шаг, который будет основной функцией во время работы. В коде шага есть взмах инструмента, за время работы функции, у робота отнимется энергия на работу всех компонентов - робот 0.25, чтение диска 0.1, слип 0.1, чанклоадер (если предварительно включили) и что там еще энергию потребляет. Измеряем заряд батарей заново, отнимаем от старого новый. energy-computer.energy() Округляем вверх, записываем в переменную E_C На каждый шаг, робот будет тратить энергию, в количестве E_C. Делим текущий заряд на это количество, получаем количество доступных шагов, сравниваем с расстоянием до базы и принимаем решение копать дальше ..или идти домой.
  10. Может опечатка? Вот рабочий код: local robot = component.proxy(component.list('robot')()) while true do computer.beep(20, 0.5) if robot.detect(3) then robot.swing(3) end end
  11. Doob

    Робот с геосканером. Часть #5 [тонкий расчет]

    Со стандартным конфигом 1.7.4 робот расходует любые инструменты на 4 действия эффективней игрока. А с зачарованными/модифицированными инструментами куча багов, вроде-бы появились после апгрейда функции robot.swing(), а может были и раньше. Но работать можно. В функции step() есть взмах инструментом и перемещение, до любой точки робот может дойти, сделав всего 3 поворота. Дополнительный запас хода будем учитывать в основном цикле, когда будет ясно, какие действия нужно выполнить, кроме движения (будет еще чистка инвентаря, упаковка и сброс лута).
  12. Doob

    Робот с геосканером. Часть #4 [оптимизация компаса]

    Это да. Я оставлял условия запуска на совесть пользователя, но можно сделать остановку программы, при их несоблюдении.
  13. При запуске программы надо оценить возможности робота, чтобы в дальнейшем, можно было точно знать количество энергии для перехода на точку старта. Робот должен измерить уровень энергии, сделать шаг, измерить еще раз и вычислить разницу. Эту разницу будет учитывать при измерении расстояния и принимать решение - идти домой или не идти. Функция robot.durability() не показывает правильный износ для зачарованных инструментов. Придется несколько раз ставить и разрушать блок, пока не обнаружится износ. Вынесем пока это все в отдельную функцию calibration() local function calibration() -- калибровка при запуске local energy = computer.energy() -- получить уровень энергии step(0) -- сделать шаг E_C = math.ceil(energy-computer.energy()) -- записать уровень потребления energy = robot.durability() -- получить уровень износа/разряда инструмента while energy == robot.durability() do -- пока не обнаружена разница robot.place(1) -- установить блок robot.swing(1) -- разрушить блок end W_R = energy-robot.durability() -- записать результат step(1) -- вернуться на место end Переменные E_C и W_R выносим в обую область видимости. Во время работы, например, после четырех сканов, робот будет оценивать количество доступных шагов по этой формуле: math.min(robot.durability()/W_R, computer.energy()/E_C) и сравнивать с расстоянием до точки старта. Из-за магической механики, зачарованные инструменты (Unbreaking) изнашиваются неравномерно, но роботу это нисколько не мешает.
  14. Геосканер потребляет много энергии, а функция compass() делает по 4 скана, пока не установит направление. Надо это исправить. Пусть робот сначала проверит наличие блока перед носом, сделает скан всех блоков вокруг себя, затем сломает блок и проверит разницу в полученных данных. Таким образом, будет производиться всего два сканирования, в прошлой версии их могло быть бесконечно много - если рядом нет блоков, робот бы крутился и молотил инструментом по воздуху, попутно делая по 4 сканирования. Улучшенная функция будет выглядеть так: local function compass() local sides = {2, 1, 3, 0} -- линки сторон света, для сырых данных D = nil -- обнуление направления while not D do -- пока не найдено направление if robot.detect(3) then -- проверить наличие блока перед носом local A = geolyzer.scan(-1, -1, 0, 3, 3, 1) -- сделать первый скан robot.swing(3) -- сломать блок local B = geolyzer.scan(-1, -1, 0, 3, 3, 1) -- сделать второй скан for n = 2, 8, 2 do -- обойти смежные блоки в таблице if math.ceil(B[n])-math.ceil(A[n])<0 then -- если блок исчез D = sides[n/2] -- установить новое направление break -- выйти из цикла end end else turn() -- задействовать простой поворот end end end
  15. Тут какое-то сильное колдунство. В 1.7.10 чанки дюпают это всем понятно, но в данном случае программа должна выполняться дальше, даже после сотни дюпов. Я немного не понял, как будет вести себя computer.uptime() после отката чанка, вроде-бы оно привязано к времени всего мира. Но в любом случае, назад оно не пойдет. Надо повесить хук и при очередном таком баге отловить значения computer.uptime() и timestamp в основном цикле до проверки.
×