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

Лидеры


Популярный контент

Показан контент с высокой репутацией 17.02.2019 в Записи блога

  1. 3 балла
    Робот может двигаться, пора добавить функцию сканирования породы и калибровки компаса. (Пока тестировал, обнаружил баг работы с зачарованными инструментами, пришлось немного переделать функцию step() - теперь после неудачного свинга, робот дополнительно проверяет наличие блока. Можно будет оставить, даже когда разрабы это исправят) Чтобы отфильтровать блоки по плотности, надо получить плотность нужных блоков с учетом шумов. На расстоянии x8 z8 y1 от геосканера, максимальная плотность бедрока равна -0.317, внесем в фильтр -0.31. Для руды 3.683, но это ванильная руда, в модах бывает и больше. Минимальная плотность обсидиана 49.312, значит, eсли он не нужен, установим для полезных блоков максимальную плотность 40. C минимальной плотностью не все так гладко. Свинцовая руда из индастриала имеет плотность 2.5 это как у деревянных предметов, разброс с учетом шума от 1.3 до 2.7, это пересекается с камнем, у которого 0.8 - 2.2. Вот таблица некоторых блоков с минимальной и максимальной плотностью: Руда 2.312 - 3.683 Стекло -0.388 - 0.983 Камень 0.812 - 2.183 Грязь -0.188 - 1.183 Сундук 1.312 - 2.683 Обсидиан 49.312 - 50.683 Видно, что плотность стекла пересекается с плотностью коренной породы, но у бедрока приоритет выше, поэтому лучше лишний раз обойти. Исходя из этих данных, полезные блоки будут отмечаться с минимальной плотностью 2.3 и максимальной 40 Теперь опишем функцию сканирования. Заглянем в подсказку. Чтобы получить сырые данные, зададим координаты и размеры квадрата, относительно сканера. geolyzer.scan(позиция_х, позиция_z, позиция_y, ширина, длина, высота) Так как один раз можно отканировать только 64 блока, будем делать 4 подхода, получая координаты квадрата по горизонтали из вызывающей функции. Преобразовываем данные в координаты, попутно анализируя плотность условным оператором и устанавливаем метки. При обнаружении бедрока устанавливаем соответсвующий флаг во внешней для всех функций переменной. Получаем функцию scan(), выглядеть она будет примерно так: local function scan(xx, zz) -- сканирование квадрата x8 относительно робота local raw, index = geolyzer.scan(xx, zz, -1, 8, 8, 1), 1 -- получить сырые данные, установить индекс в начало таблицы for z = zz, zz+7 do -- развертка данных по z for x = xx, xx+7 do -- развертка данных по х if raw[index] >= 2.3 and raw[index] <= 40 then -- если обнаружен блок с плотностью от 2.3 до 40 table.insert(WORLD.x, X+x) --| записать метку в список table.insert(WORLD.y, Y-1) --| с коррекцией локальных table.insert(WORLD.z, Z+z) --| координат геосканера elseif raw[index] < -0.31 then -- если обнаружен блок с отрицательной плотностью border = true -- сделать отметку end index = index + 1 -- переход к следующему индексу сырых даннх end end end Раз уже взялись за геосканер, напишем и компас. Чтобы определить стороны света, надо сломать блок перед носом, просканировать его, затем установить обратно и, если есть разница - выдать результат. Для большей надежности добавим вращение вокруг своей оси, т. к. блока перед носом может и не быть или быть, но не тот. Координаты блоков задаем в таблице, сбрасываем текущее направление, определяем заново, вот и вся функция. Назовем ее compass() local function compass() -- определение сторон света local sides = {{-1,0}, {0,-1}, {1,0}, [0]={0,1}} -- привязка значений сторон света к смежным блокам D = nil -- обнуление текущего направления while not D do -- пока направление не найдено for n = 0, 3 do -- перебор сторон света robot.swing(3) -- разрушение блока if geolyzer.scan(sides[n][1], sides[n][2], 0, 1, 1, 1)[1] == 0 and robot.place(3) then -- тестовое сканирование и установка блока if geolyzer.scan(sides[n][1], sides[n][2], 0, 1, 1, 1)[1] > 0 then -- если обнаружена разница в сканах D = n -- установить новое направление break -- выйти из цикла end end end turn() -- задействовать простой поворот end end Самые важные функции готовы, можно приступить к тестированию.
  2. 2 балла
    Ядро копателя готово, теперь можно и пощупать. Напишем пробную функцию сканирования и добычи одного слоя. Сначала откалибруем компас и зададим таблицу с координатами сканируемых квадратов. Затем, отсканируем квадрат 16 на 16 блоков, выведем количество обнаруженных блоков. И в цикле обойдем все метки. Вроде бы все просто. Ах, да... будем искать ближайший блок к текущей позиции, чтобы быстрее закончить работу. Есть много подходов к определению расстояний. Например квадрат гипотенузы равен сумме квадратов катетов, формула для нашего случая будет math.sqrt((X-x)^2+(Z-z)^2), где X,Z - координаты робота, x,z - координаты метки, можно выкинуть квадратный корень, в нашем случае бесполезный и даже вредный. Но тут есть одно "но", мы получили гипотенузу, а это наименьшее расстояние между точками, а роботы по диагонали не ходят. Я буду вычислять дельту между точками, суммируя реальное расстояние, которое пройдет робот по формуле math.abs(X-x)+math.abs(Z-z) Эта операция в сферическом вакууме потребляет на 5% больше процессорного времени, чем предыдущая, но с лихвой окупается сэкономленными шагами. В цикле будем обходить таблицу с метками, до каждой вычисляя расстояние, самый лучший результат с индексом будем хранить в отдельных переменных. По окончании работы цикла, будем посылать робота в ближайшую точку. Код всей тестовой программы под спойлером. А вот и видео с демонстрацией. Можно добавить штрафы на повороты, тогда он будет меньше крутиться и собирать кучи линейкой, а не змейкой.
  3. 1 балл
    При запуске программы надо оценить возможности робота, чтобы в дальнейшем, можно было точно знать количество энергии для перехода на точку старта. Робот должен измерить уровень энергии, сделать шаг, измерить еще раз и вычислить разницу. Эту разницу будет учитывать при измерении расстояния и принимать решение - идти домой или не идти. Функция 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) изнашиваются неравномерно, но роботу это нисколько не мешает.
  4. 1 балл
    Геосканер потребляет много энергии, а функция 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
Эта таблица лидеров рассчитана в Москва/GMT+03:00
×
×
  • Создать...