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

quarry карьер

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

вроде всё отладил, завтра протестирую, если всё норм выложу

 

меня беспокоит ещё один момент, можно ещё немного ускорить копание убрав постоянную проверку инструмента

404 tool()

в гео-копалке @Doob использован интересный метод, работающий на тёмной магии :D

Скрытый текст

local W_R = 0 -- скорость износа
local delta = math.abs(X)+math.abs(Y)+math.abs(Z)+64 -- определить расстояние
if robot.durability()/W_R < delta then -- если инструмент изношен

 

надо бы поколдовать на досуге

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

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


Ссылка на сообщение
Поделиться на других сайтах
10 часов назад, serafim сказал:

в гео-копалке @Doob использован интересный метод, работающий на тёмной магии 

Магия тут вполне себе светлая.

 

@Doob находит скорость износа экспериментально, совершая несколько попыток применения инструмента, т.к. робот изнашивает инструмент не при каждом использовании, а с некоторой вероятностью, определённой в файле конфигурации OpenComputers. Метод медленный, но не требующий наличия контроллера инвентаря в роботе. Контроллер же инвентаря позволит выполнить эту операцию быстрее: W_R = 1/maxDamage.

 

Запоздалое, но важное дополнение к абзацу выше: Метод, использующий контроллер инвентаря, успешно работает только с обычными инструментами. Значение maxDamage для перезаряжаемого инструмента имеет другой смысл.

 

А здесь обратная операция: robot.durability()/W_R, остаток прочности инструмента переводится в остаточное количество использований инструмента. Реальное количество при стандартном конфиге примерно в 10 раз больше, но гарантированное количество именно такое.

 

Это количество сравнивается с манхэттенским расстоянием до исходной позиции робота. Именно такое количество блоков может потребоваться прорубить при возвращении. К этому добавляется запас в 64 блока. Скорее всего, это максимальное количество движений, которое может потребоваться для полной выработки слоя. Если я верно помню, эта копалка копает столбиками площадью 8x8=64 блока.

 

10 часов назад, serafim сказал:

можно ещё немного ускорить копание убрав постоянную проверку инструмента

Да, именно так. Вызвав robot.durability(), имеет смысл сразу сохранить остаток использования инструмента в переменную и декрементировать её при каждом успешном использовании инструмента. Но при снижении её значения ниже критического уровня не надо сразу бежать на базу, а следует перечитать robot.durability() ещё раз и уже после этого принимать решение.

 

@Doob решил эту задачу иначе. Его программа уже знает, что слой может быть полностью выкопан до того, как возникнет необходимости вернуться на базу, и проверяет прочность инструмента после обработки очередного слоя. Такая частота проверки, скорее всего, избыточна, и robot.durability() можно вызывать реже.

Изменено пользователем eu_tomat
дополнение

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


Ссылка на сообщение
Поделиться на других сайтах
10 часов назад, serafim сказал:

бур в режиме 3х3 ?

С киркой алмазной

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


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

Проверил все правки, залил обнову, ссылка таже

Теперь алгоритм копания и движение немного эффективней работает

Бур в режиме 3х3 баги не вызывает, но движение робота под этот режим копания не заточен, робот будет делать лишние повороты

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


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

Если подумать, то весь объём мне не требуется вычислять, достаточно знать сколько блоков в линии (х),

и хватит ли инструменту прочности чтоб эту линию выкопать

 

к примеру:

x = 16

durability = 1500

w_r = x*3/durability+16

*3 потому что в одной линии 3 ряда блоков

+16 запас на манёвры, но лучше использовать значение (х) чтоб наверняка докопать

 

или сделать сравнение if durability > x*3+х then

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

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


Ссылка на сообщение
Поделиться на других сайтах
4 часа назад, serafim сказал:

Если подумать, то весь объём мне не требуется вычислять, достаточно знать сколько блоков в линии (х),

и хватит ли инструменту прочности чтоб эту линию выкопать

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

 

На сравнительно коротких дистанциях для работа более важна способность корректного возврата ровно к той позиции, где он прервал свою работу. Предложенная же эвристика не способствует экономии времени, потому что затраты на проверку прочности инструмента крайне малы в сравнении со временем, затрачиваемым роботом на перемещение к заряднику.

 

Разберём несколько примеров. Для упрощения предположим, что роботу для рубки блоков не требуются перемещения, блоки каким-то образом сами появляются перед роботом. Но для зарядки инструмента роботу требуется переместиться на 10 шагов к заряднику и обратно. Пусть на рубку одного блока требуется 8 тиков. Столько же требуется для единичного перемещения. Также предположим, что инструмент заряжается мгновенно, и для его зарядки робот тратит время лишь на дорогу.

 

1) Остаток прочности инструмента: 1000/1000.

Очевидно, что в этом случае нет смысла перемещаться к заряднику, а можно смело рубить 1000 блоков, сразу после проверки реальной прочности инструмента один раз перед началом работы. Накладные расходы: 1/(8*1000) = 0.000125.

 

2) Остаток прочности инструмента: 100/1000.

Если робот сразу приступает к работе, то накладные расходы = 1/(8*100) = 0.00125

Если робот сначала идёт к заряднику, то накладные расходы = (1+20*8)/8*1000 = 0.020125

Видно, что к заряднику идти не выгодно, имеет смысл сначала израсходовать имеющуюся прочность инструмента.

 

3) Остаток прочности инструмента: 7/1000.

Если робот сразу приступает к работе, то накладные расходы = 1/(8*7) = 0.018

Если робот сначала идёт к заряднику, то накладные расходы = (1+20*8)/8*1000 = 0.020125

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

 

4) Остаток прочности инструмента: 6/1000.

Если робот сразу приступает к работе, то накладные расходы = 1/(8*6) = 0.0208

Если робот сначала идёт к заряднику, то накладные расходы = (1+20*8)/8*1000 = 0.020125

А уже в этом случае теряется смысл расходовать прочность инструмента до последнего, выгоднее сначала зарядиться.

 

А теперь другой пример: расстояние до зарядника = 40, остаток прочности 2/1000.

Если робот сначала идёт к заряднику, то накладные расходы = (1+80*8)/8*1000 = 0.080125

Если робот сразу приступает к работе, то накладные расходы = 1/(8*3) = 0.0625

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

 

Вывод: Для экономии времени на вызовах robot.durability() нет смысла дробить работу на крупные блоки. Запас в 48 блоков приведёт не к увеличению, а снижению скорости копки. Дополнительный смысл такого решения может появиться при длинных челночных проходах роботом или же для упрощения кода, чтобы не прерывать копку в произвольных точках карьера.

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


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

В итоге пришёл к такому коду, для проверки хватит ли выкопать линию

Скрытый текст

if r.durability() == nil or 100*r.durability() <= length*3+length then

 

 

38 минут назад, eu_tomat сказал:

Для экономии времени на вызовах robot.durability() нет смысла дробить работу на крупные блоки. Запас в 48 блоков приведёт не к увеличению, а снижению скорости копки

Ну ок, пусть будет как есть

 

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


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, serafim сказал:

Ну ок, пусть будет как есть

Как будет? Пусть скорость снижается, но упростится код?

 

1 час назад, serafim сказал:

В итоге пришёл к такому коду, для проверки хватит ли выкопать линию


if r.durability() == nil or 100*r.durability() <= length*3+length then

Ну, хорошо. Если упрощаем код, тогда и robot.durability() можно вызывать два раза подряд, это уже не играет особой роли. Но почему константа 100 захардкожена? Разве она не должна зависеть от используемого инструмента?

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


Ссылка на сообщение
Поделиться на других сайтах
23 минуты назад, eu_tomat сказал:

Как будет? Пусть скорость снижается, но упростится код?

пока без изменений, с частой проверкой прочности

if r.durability() == nil or r.durability() <= 0.03 then

А вообще протестирую, какой вариант лучше будет, но судя по расчётам то без изменений

 

23 минуты назад, eu_tomat сказал:

почему константа 100 захардкожена? Разве она не должна зависеть от используемого инструмента?

if r.durability() == nil or 100*r.durability() <= length*3+length then

robot.durability() возвращает дробное значение от 1 до 0 в виде 0,950 ,  100 - это округление к 95 (возможно надо до 1000)

length*3 длина линии Х в три ряда

+length  запас прочности на манёвры, в принципе можно поставить 16 (тут надо тесты)

в общем это не финальный вариант для расчётов

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

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


Ссылка на сообщение
Поделиться на других сайтах
2 минуты назад, serafim сказал:

судя по расчётам то без изменений

Если речь идёт о моих расчётах, то оптимально делать так:

18 часов назад, eu_tomat сказал:

Вызвав robot.durability(), имеет смысл сразу сохранить остаток использования инструмента в переменную и декрементировать её при каждом успешном использовании инструмента. Но при снижении её значения ниже критического уровня не надо сразу бежать на базу, а следует перечитать robot.durability() ещё раз и уже после этого принимать решение.

То есть, вызывать robot.durability() следует как можно реже, самостоятельно довычисляя рабочее значение остатка прочности. Это позволит получить выигрыш во времени около 2-3%. И ездить на зарядку тоже следует как можно реже, не дробя работу на крупные куски. Если, конечно, смотреть с точки зрения оптимизации.

 

14 минуты назад, serafim сказал:

robot.durability() возвращает дробное значение от 1-0  виде 0,950 ,  100 - это округление к 95%

А что нам даст знание о целых процентах? Остаток прочности, выраженный в гарантированном количестве оставшихся использований, можно напрямую сравнивать с объёмом работы. А проценты какой смысл сравнивать? Это же относительная величина.

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


Ссылка на сообщение
Поделиться на других сайтах
4 минуты назад, eu_tomat сказал:

вызывать robot.durability() следует как можно реже, самостоятельно довычисляя рабочее значение остатка прочности. Это позволит получить выигрыш во времени около 2-3%

да, вариант неплохой

5 минут назад, eu_tomat сказал:

Остаток прочности, выраженный в гарантированном количестве оставшихся использований, можно напрямую сравнивать с объёмом работы

Я пока не могу собраться с мыслями как это сделать

значение прочности вида 0,950 хотел перевести в количество блоков, которое осталось кирке копать

но вполне возможно это неверный подход

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


Ссылка на сообщение
Поделиться на других сайтах
21 час назад, eu_tomat сказал:

робот изнашивает инструмент не при каждом использовании, а с некоторой вероятностью, определённой в файле конфигурации OpenComputers

вот этот конфиг по умолчанию

Скрытый текст

# Степень разрушения предметов при использовании их роботами. Значение
# 1 означает, что они ломаются с той же скоростью, что и при использовании
# игроком. 0 означает, что инструменты не ломаются вообще. 
# Этот параметр влияет только на те инструменты, которые можно сломать.
itemDamageRate=0.1

Игрок расходует кирку со значением 1 а вот робот 0,1

Например прочность железной кирки = 251, игрок сломает 251 блок, а вот робот по замерам может и 500 блоков сломать

Видимо придётся делать примерный замер на сколько расходуется инструмент за удар, так как делал doob

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


Ссылка на сообщение
Поделиться на других сайтах
1 минуту назад, serafim сказал:

Игрок расходует кирку со значением 1 а вот робот 0,1

Не совсем так. Робот также снижает прочность кирки на единицу, но с шансом 0.1, т.е., в среднем один раз из 10. Таким образом, робот железной киркой может добыть не 251 блок, а в среднем 2510 блоков. Но это в среднем. В каждом конкретном случае может быть больше, а может быть меньше в зависимости от выпадения шанса.

 

5 минут назад, serafim сказал:

Видимо придётся делать примерный замер на сколько расходуется инструмент за удар, так как делал doob

Да. Причём, можно исхитриться и выполнять замер не отдельной процедурой, а прямо во время работы. И так, наверное, даже более правильно.

 

И да, ты прав, это значение примерное. С точки зрения идеальной математики оно должно быть взаимно обратным значению максимальной прочности. Но погрешности вещественных типов приводят к расхождению, если максимальная прочность большая. Я уже не помню, насколько большим было это расхождение, но точно помню, что оно не не корректировалось округлением до ближайшего целого. Поэтому правильным способом будет непрерывное уточнение значения в процессе использования инструмента. Конечно же, если есть желание получить максимально точное значение максимальной прочности инструмента.

 

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

 

Кстати, с синим буром в режиме 3x3 опять будет сложность: он теряет заряд пропорционально количеству срубленных блоков, которое не всегда одинаково и зависит от конфигурации встреченных полостей.

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


Ссылка на сообщение
Поделиться на других сайтах
4 минуты назад, eu_tomat сказал:

робот железной киркой может добыть не 251 блок, а в среднем 2510 блоков

Уф, это прям плюс минус километр, так робот никуда не доедет

5 минут назад, eu_tomat сказал:

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

А вот эта идея интересная

Вместо очень примерных замеров, можно сделать "режим паника"

Сначала делать замер износа инструмента только в начале и в конце линии, и в случае износа меньше определённого значения (например 20%) проверять износ при каждом движении, да это не так эффективно, но робот точно не застрянет

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


Ссылка на сообщение
Поделиться на других сайтах
9 часов назад, serafim сказал:

Вместо очень примерных замеров, можно сделать "режим паника"

Сначала делать замер износа инструмента только в начале и в конце линии, и в случае износа меньше определённого значения (например 20%) проверять износ при каждом движении, да это не так эффективно, но робот точно не застрянет

Без паники! Тяжело точно измерить объём полной бочки напёрстками, даже заранее зная, что она содержит целое число напёрстков. Небольшая погрешность легко может накопиться в один-два лишних или недостающих напёрстка. Но когда ты измеряешь небольшой остаток воды в бочке, всё так же зная, что количество напёрстков должно быть целым, ошибиться почти невозможно. Погрешность вычислений снижается естественным образом, и округление до целого полностью решает эту проблему.

 

А учитывая, что мы не доверяем шансам, то и частоту проверки остатка прочности мы также увеличиваем по мере падения прочности. Покажу это на примере всё той же железной кирки:

 

robot.durability() показывает прочность примерно в 251 использование. В среднем кирка износится за 2510 использований. Поэтому даже  если мы получили слегка завышенную прочность, мы вряд ли сломаем кирку до конца, применив её, например 252 раза. Если тебя интересует вероятность неудачного исхода в таком применении, я могу потормошить голову и посчитать. Это как-то связано с биномом Ньютона, но мне требуется вспомнить, как именно.

 

Но идём дальше. Предположим, мы использовали кирку 252 раза. За это время она износится в среднем на 25 единиц. Мы снова проверяем остаток через robot.durability() и получаем остаток прочности, равный, например, 226. И теперь мы используем кирку 226 раз.

 

В следующий раз мы используем кирку 204 раз, затем 184 раза, затем 166 и т.д. Чем ниже остаток прочности, тем чаще выполняется его проверка. При таком алгоритме сложно проскочить критический момент. Особенно учитывая, что по мере приближения к нему точность вычислений возрастает по причине естественного снижения погрешности.

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


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

Я сейчас повторил эксперимент в игре и обнаружил, что значимых проблем с точностью нет. Можно округлять до 6 знака после запятой, и всё будет сходиться. Но откуда могла взяться ошибка в моём прошлом эксперименте? Подозреваю, что в тот раз я не глядя взял значения с википедии, а увидев расхождение, не довёл эксперимент до конца.

 

Рассмотрю проблему на примере алмазной кирки. Согласно вики, её прочность равна 1562. Проверка прочности через контроллер инвентаря:

component.inventory_controller.getStackInInternalSlot(1).maxDamage
1561.0

Проверка прочности при использовании:

d0=robot.durability()
repeat
  robot.place()
  robot.swing()
  d=robot.durability()
until d~=d0 dura=1/(d0-d)
print(dura,(dura*1e6+0.5)//1/1e6)

1560.9999999999 1561.0

Значение максимальной прочности кирки, полученное экспериментально, совпадает со значением, полученным с помощью контроллера инвентаря с погрешностью до 6 знака после запятой. На самом деле погрешность ещё меньше, просто я не увидел смысла в её точном определении.

 

Вики, к слову, тоже не врёт, если вникнуть в механику использования инструмента. После рубки алмазной киркой 1561 блока остаток прочности кирки будет равен нулю. Но даже нулевая прочность позволит сломать ещё один блок, при этом кирка окончательно сломается.

 

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


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

@Asummonster я частенько вижу реакцию "в шоке" под своими постами, но мне ни разу не удалось понять, что она означает. Вот, скажи: выставляя реакцию "в шоке", какую мысль ты хочешь донести до автора поста и до его читателей? Что именно тебя шокирует? Ты с чем-то не согласен? Или согласен, но считаешь неприемлемым высказывать это? Или согласен, но не ожидал такого решения? Или наоборот, решение для тебя настолько очевидным, что тебя шокирует его обсуждение? Ты хочешь видеть подобные посты чаще, или наоборот, реже?

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


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, eu_tomat сказал:

@Asummonster я частенько вижу реакцию "в шоке" под своими постами, но мне ни разу не удалось понять, что она означает. Вот, скажи: выставляя реакцию "в шоке", какую мысль ты хочешь донести до автора поста и до его читателей? Что именно тебя шокирует? Ты с чем-то не согласен? Или согласен, но считаешь неприемлемым высказывать это? Или согласен, но не ожидал такого решения? Или наоборот, решение для тебя настолько очевидным, что тебя шокирует его обсуждение? Ты хочешь видеть подобные посты чаще, или наоборот, реже?

Шокирует глубина погружения в каждый вопрос, который ты берёшься разбирать. Поразительно. Восхитительно. Давай ещё.

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


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

Продолжу заниматься осветлением тёмной магии. Мне в личку поступил вопрос о назначении конструкции (dura*1e6+0.5)//1/1e6. Подозреваю, что эта информация будет интересна более широкому кругу читателей, поэтому публикую свой ответ здесь.

 

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

 

Что такое 1e6?

Если рассуждать логически, то можно предположить, что это какая-то причудливая форма записи числа. Поиск по фразе «форма записи числа» быстро приводит к статьям, рассказывающим о форме записи, называемой формой записи числа с плавающей точкой. Синонимы: «экспоненциальная запись», «научная форма», «нормальная форма», «полулогарифмическая форма». Примеры:
1e6 = 1 * 10^6 = 1000000.
5e-3 = 5 *10^-3 = 0.005


Я использую экспоненциальную запись для краткости. От обилия ноликов у меня рябит в глазах, а в экспоненциальной форме я сразу вижу количество нулей, что снижает вероятность ошибки.

 

Что такое //?
Это операция целочисленного деления. Как об этом узнать? Во-первых, можно загуглить фразу «lua double slash operator». Можно и на русском языке поискать, но шанс найти подобное упоминание будет ниже. Во-вторых, имеет смысл читать спецификации языка, это основной источник знаний: Lua 5.3 Reference Manual 3.4.1 – Arithmetic Operators. Также есть справочник по языку Lua5.3 на русском: http://antirek.github.io/luabook/.

 

Что вообще делает конструкция (dura*1e6+0.5)//1/1e6?
Я использую операцию целочисленного деления для получения целочисленной части числа. По-моему, это самый быстрый способ. Иначе говоря, это округление числа до целого вниз. Но перед этим я добавляю к числу 0.5, для того, чтобы получить округление до ближайшего целого.

Перед  округлением до целого я умножаю исходное число на 1e6, а после округления делю результат на 1e6. Эта последовательность операций позволяет мне округлить число до 6 знака после запятой.

 

Если кто-то знает более эффективный способ округления чисел, делитесь своими решениями. Я же использую эту конструкцию с тех пор, как перешёл на Lua5.3.


Для вычисления прочности инструмента, скорее всего, достаточно было бы тупо округлять число до ближайшего целого, но в экспериментах я стараюсь округлять хотя бы до 6 знака, чтобы убедиться, что располагаю запасом точности, и меня не ждут сюрпризы с этой стороны.

 

Когда мне требуется максимальная точность, я подбором ищу самый далёкий знак, чтобы округление искажало результаты минимальным образом, но было бы достаточным для получения устойчивых и воспроизводимых результатов. Такой подход иногда позволяет мне обнаруживать новые нюансы механик во время дальнейших экспериментов. Например, если сначала мне хватало округления до 9 знака, но на каком-то этапе вдруг потребовалось округление до 6. Такое изменение может означать встречу с каким-то новым эффектом. Или, например, может сигнализировать мне о том, что я использовал слишком громоздкие вычисления приводящие к сильному снижению точности.

 

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

 

Надеюсь, этот пост будет полезен более чем одному читателю форума.

 

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


Ссылка на сообщение
Поделиться на других сайтах
  1. if tru >= 10 then
  2.       tru = 0
  3.       returnHome("непреодолимое препятствие",true)
Изменил 10 на 100 на 435 строке. Перестал ложно возвращаться с непреодолимым препятствием. Играю на сервере и думаю, что дело в лагах.

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


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

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

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

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

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

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

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

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

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


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