Робот с геосканером. Часть #2 [сканирование]
Робот может двигаться, пора добавить функцию сканирования породы и калибровки компаса.
(Пока тестировал, обнаружил баг работы с зачарованными инструментами, пришлось немного переделать функцию 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
Самые важные функции готовы, можно приступить к тестированию.
- 5
0 комментариев
Рекомендуемые комментарии
Нет комментариев для отображения