Krutoy
-
Публикации
482 -
Зарегистрирован
-
Посещение
-
Победитель дней
72
Сообщения, опубликованные пользователем Krutoy
-
-
Один из игроков в мой модпак сделал видео по тому как сделать убивающего робота.
-
1
-
1
-
1
-
-
20 часов назад, eu_tomat сказал:А что там в ролике за бутылочка, ускоряющая сборку робота?
И как ты сделал рецепт крафта своей EEPROM?
Бутылочка - Time In The Bottle из мода Random Things
Рецепт я сделал с помощью мода CraftTweaker. Я ведь разрабатываю свой модпак и могу делать какие угодно рецепты.
-
1
-
-
Записал небольшой гайд о простом функционале
-
3
-
1
-
-
31 минуту назад, eu_tomat сказал:А что мешает?
Например то, что будет очень сложно засунуть в EEPROM настоящий парсер со своим мощным синтаксисом
-
1 минуту назад, eu_tomat сказал:Но в конечном-то итоге ты хочешь сократить количество символов не в коде Lua, а в коде на твоём специфическом языке. И если правила этого языка ты определяешь сам, то можно создавать в принципе любые правила. Например, можно любое выражение присваивания интерпретировать по правилам языка Си. В каких-то случаях присваивание продолжится, в каких-то случаях оно окажется однократным, а иногда будет и вовсе отсутствовать, как это бывает с результатами вызова функций.
Ну да, в этом и суть. Я придумываю правила сам.
Вот только я не пишу свой парсер. Я придерживаюсь синтаксиса Луа, а поэтому, не могу сделать из присваивания выражение.
-
13 часа назад, Taruu сказал:Идея крутая, но чую что тут не хватает аля SPA простого который тупо рисовал блок-схемы или человеко читаемый код. А при желании еще и разжевывал что каждая команда делает с примерами и видосами. Но там кол-во работы настолько большое что повеситься можно >_<
Мне кажется, делать "читаемый код" тут бессмысленно. Это как когда ты был в школе - тебе объяснили что такое знак +. Там не было никаких SPA схем или "человеко читаемый код". Может, показали пару-тройку яблок что бы объяснить что такое сложение.
Думаю так же и здесь. Пару десятков раз заходишь в справочник что какой знак делает, потом привыкаешь.
Да и я если честно, сам не совсем понимаю, как делать "человеко-читаемый код" в функциональном программировании.
Например, есть оператор "apply" или по-русски "применение". В моем коде он выглядит как f/n, где f - функция, n - число или boolean. Результат будет выглядеть вот так:
-- f/n function(...) return f(n, ...) end
А теперь еще раз используем "применение":
-- f/a/b function(...) return (function(...) return f(a, ...) end)(b, ...) end
У меня если честно мозг устает такой "читаемый код" делать. 😅
-
В 03.03.2023 в 11:31, eu_tomat сказал:Какова конечная цель этого трюка?
Цель этого трюка - сократить количество символов в коде.
Пример из реального кода:
У нас есть точка из Навигатора дрона
P=navigation.findWaypoints(300)
Дальше по коду, мы полетим к этому вейпоинту, подождем, а затем выполним его название
drone.move(table.unpack(P.position)) while drone.getOffset() > 1 do sleep(1) end run(P.label)
В моем сокращении это всё выглядит так:
P=i/Nf300ⓡDm^Pp,s/1~'Dg!>1',_(Pl)
Допустим, я сделаю ту функцию
function _P(v) P = v; return P end
Тогда сокращение будет выглядить так:
_P(i/Nf300),Dm^Pp,s/1~'Dg!>1',_(Pl)И это только увеличило количество символов на +1 😃
-
Если кто то читает эту тему, подскажите - как сделать присваивание внутри выражения?
Например, есть вот такой код:
_1_ function f() return _2_ end
Я могу менять только _1_ и _2_. Я хочу что бы в _2_ было присваивание и тут же использование этой переменной.
Например
a=robot.move -- присваивание not a(3) and robot.turn(true) -- выражение
Пока надумалось только такое решение - сделать функцию, которая будет присваивать значение глобальной переменной. Но этот вариант выглядит криво
function _a(v) a = v end function f() return _a(robot.move), a(3) end
-
В общем, похоже вырисовывается в какой-то мере стабильно работающий код.
Пока вся документация на английском:
https://github.com/Krutoy242/lostuser
В общем, я сохранил правила укорачивания и добавил больше функций между таблицами и функциями.
Приведу пример дрона, который носит предметы между точками.
Компоненты: Инвентарь, Контроллер инвентаря
Имя дрона:
P=i/Nf300ⓡDm^Pp,s/1~'Dg!>1',_(Pl)
Описание каждой части имени:
-
Nf300: Выполняетnavigation.findWaypoints(300). Это никакое заранее указанное сокращение. Большая буква - это сокращение, которое получают все компоненты. navigation -> N, inventory_controller -> I и так далее. -
i/Nf300: Здесь используется единственная предустановленная переменная i. i = порядковый индекс текущего цикла программы, начиная с нуля.i / table- специальная функция "Получить индекс по модулю" илиt[i % #t + 1]. Все эти функции, которые есть математические операторы над таблицами, есть в документации. По смыслу мы просто пробегаем каждый цикл по следующему вейпоинту. -
P=i/Nf300: Просто записываем в глобальную переменную P наш вейпоинт. Локальные переменные не могут сокращаться, поэтому мы используем глобальную. А еще, если буква будет большая, мы сможем сократить точку далее. -
ⓡ: просто один символ который будет заменен наreturn. Приму советы как избежать таких замен, что бы сохранить чистый Lua код 🙂 -
Dm^Pp: вызываетdrone.move(table.unpack(P.position)). Тут должно быть просто. Dm => D.m => drone.m => drone.move. В документации по ссылке выше перечислены все операторы, и там написано что если функцию (drone.move) возвести в степень таблицы (p.position) то мы получим вызов функции с раскрытием таблицы в параметры. -
s/1~'Dg!>1'=>while drone.getOffset() > 1 do sleep(1) end. Здесь символ ! заменяется на () -
_(Pl): ЗагрузитьP.labelкак Lua код. Эта функция будет загружена и выполнена. Точки называются _'Dsk0'~4
и _'Dsel(k)Dd(0)'~4 соответственно. Первая сосет 4 раза, вторая выбирает каждый из 4х слотов и поочереди их выбрасывает.
-
4
-
-
Продолжаю программировать.
Понял что моя "труба" на самом деле называется "map". И теперь переписал код, что бы оператор map был через "*".
Еще, "/" это `filter(v)`, а "%" это оператор "reduce(a,b)"
T = q({{index=1},{name='n2'},{index=3}}) print(T*'v.i'/'v'%'a+b') -- 4
Осталось понять, что должно происходить, если мы делаем фильтр в таблицу или фильтр в число.
-
Ок, тогда я могу делать трубу в строку
Вот, чистый луа код без замены символов
Tg()|'a1.tr()'
Превращается в (еще оборачивается в pcall что бы ошибок не было при итерации)
for k,v in pairs(trade.getTrades()) do v.tr() end
-
1
-
-
26 минут назад, ProgramCrafter сказал:Вроде machine.lua в OpenComputers запрещал так делать.
Что ли, ещё один баг в OC нашёлся?
А machine.lua есть на EEPROM ?
Если да, то это досада =((
UPD:
Нашел... Печалька
-
Я только что понял, что я могу изменять метатаблицы строк!
Это значит, что я могу добавить методы к строкам, тем самым полностью превратив имя робота в луа-программу, без подстанов и замен.
Например, я могу добавить __bnot к строке, что будет ее загружать и превращать в функцию.
getmetatable('').__bnot=function(s)return load('return '..s) end print((~'5*5')()) -- 25
-
Ок, вот мои наработки по теме:
https://gist.githubusercontent.com/Krutoy242/1f18eaf6b262fb7ffb83c4666a93cbcc
Документацию напишу позже.
Пока, как я и говорил, робот (или дрон!) умеет выполнять свое имя как Луа-код. Но к тому же, он может всё сокращать до 1-2 символов.
Например, вот такая строка сторгует всё что есть у жителя:
~:Tg(){?!v{tr}}
А вот мега программа в 54 символ для дрона, который носит предметы из одного вейпоинта к другому:
Dm(tb.u(Nf(300)[a++%2+1].p))s(3)~#{Dsel(i)Dd(0)Dsu(0)}
В этом примере есть такие сокращения:
a++ это продвинутая версия a=a+1, только она работает даже если а==nil
s(3) расшифруется как sleep(3)
~#{BODY} получится for i=1, (R or D).inventorySize() do BODY end
Еще, я добавил крутые фичи связанные с "трубами" - как в лямбда программировании, когда мы можем скомпоновать функцию, которая будет передавать результат своей работы в другую функцию. Но пока не придумал как ими пользоваться.
Главная фишка это утилизировать битовые операции. Я сделал такое: a|b превращается в function(c) return b(a(c)) end. Но оказалось, что это почти бессмысленно, если мы не можем получить ключ\значение из цикла.
В итоге, я уже могу написать вот такую функцию:
_4|(Dsel|Dd&0)
Получится вот так (примерно):
for k,v in pairs{1,2,3,4} do (function() return D.drop(0) end)(D.select(v,k)) end
Но как то криво всё равно. Не элегантно. Но уже можно пользоваться.
-
3
-
1
-
-
10 минут назад, eu_tomat сказал:У меня есть идея, но она ломает изначальный замысел. С точки зрения пользователя я бы предпочёл использовать стандартный синтаксис Lua, и чтобы все необходимые сокращения кода за меня выполняла программа. Получилось бы подобие упаковщика кода в последовательность ASCII-символов, которые можно было бы ввести через наковальню.
Да, идея хорошая. Я думал такое сделать. Но по сути, это просто LZ77 алгоритм с распаковщиком внутри EEPROM.
Вопрос такой - как узнать все доступные в наковальне символы? Не все символы можно вставлять в название, например
§
-
Может у кого то есть еще идеи как можно укоротить всякие конструкции с заголовком / телом ?
В таких вещах как функции и циклы есть заголовок - например, таблица для pairs(t) и тело - собственно то что будет внутри блока.
Самое короткое что я придумал - 3 символа.
1. Ключевой символ начала паттерна
2. Разделитель между заголовком и телом
3. Окончание паттерна
например вот тут ~:t{pt(k,v)} это ~:1 {2 }3
Хотелось бы 2 символа или даже один.
Например, как в лямбда - счислениях a.b означает b(a())
Проблема в том, что в EEPROM запихать парсер Lua оч сложно, поэтому самый сильный инструмент у меня в доступе это "рекурсивный" паттерн %b12
-
15 минут назад, ProgramCrafter сказал:Лучше ~kv:t{pt(k,v)} (или как-то так), потому что циклы могут ведь вкладываться друг в друга.
Да, но так еще больше символов.
Вообще, я уже решил эту проблему. Все циклы работают через k,v, но при выполнении они переписываются на k0,v0 k1,v1 и так далее.
~:t{~:v{pt(k,v)}}получится
for k1,v1 in pairs(t) do for k0,v0 in pairs(v1) do print(k0,v0) end end -
Размышления по поводу программы привели меня к еще более крутой идее:
А что если я не буду придумывать никакого синтаксиса, а просто сделаю функцию сокращения путей и ключевых слов?
Изменяя метатаблицы переменной _ENV я могу наворотить любые сокращения.
Например, если назвать робота
robot.use(3)- он будет юзать вперед.
Но это можно укоротить до 5 символов. Заменим robot на R, сделаем поиск по полям, уберем ненужную точку, и вуаля, останется только
Ru(3)Еще бы сократить вызовы функции с параметрами как то, и вообще шикарно.
Еще можно упростить всякие циклы и пэирсы, например заменить for in pairs() на
~:t{pt(k,v)}Превратится в
for k,v in pairs(t) do print(k,v) end
Но тут уже начинаешь путаться.
🤔
-
1
-
-
12 часа назад, rootmaster сказал:главный вопрос, а зачем? я в своих роботов либо ставлю монитор, либо подключаю к сети дома, регистрирую на нем удаленную файловую системму(чаще всего и то и другое)(мои софтом(netoworks, distfs2)) и открываю доступ в его lua по сети, и вооля все роботом можно управлять удаленно на диск записал /start.lua(запускаеться моим модом для openOS) и как тока включил он пойдет копать
Моя версия проще. Лешего, не нужно учить луа. Скрафтил и вперёд.
-
1
-
1
-
-
3 часа назад, ECS сказал:Респект за соулс от мира опенкомпов!
Спасибо!
Тут как говорится - хотел как лучше - получилось как всегда.
ЦитатаПожалей наши мыши!
Как? Я бы рад, но как?
Может сделать какую то внутреннюю подпрограмму, которая будет расшифровывать все алиасы на месте? Типа, выводить куданибудь в output дерево расшифровки?
Цитата?{<a>==nil} эквивалентно if a == nil.
Все твои шаги расшифровки почти полностью правильно поняли мою задумку. Мне приятно видеть что хоть кто то копнул так глубоко.
Именно в этом шаге ?{<a>==nil} эквивалентно if VARS['a'] == nil, потому что иначе не нужны были бы <>.
Цитатаa - это программа, которая... что? Которая названа a?
Может, проблема в том, что в языке перемешан синтаксис языка \ алиасы и переменные? Может в таком случае, нужно что бы, например
- Весь синтаксис только на не-буквеных символах @#$
- Все переменные как маленькие буквы abc
- Все алиасы как большие ABC
Цитатаклассический эскейпинг через \" был бы правильнее
В принципе, мне не сложно добавить эскейпинг. Я это сделаю.
Правда, это больше символов в программу. Почти нет таких условий когда тебе нужно 3 раза подряд вписывать строку внутри строки.
А может подключить юникод и сделать что то такое. Правда, при больших программах это все равно растянется на страницы
-
1
-
Lost User- Самый Простой РоботЗачем?
Роботы OC сложны в сборке и программировании. Эта программа BIOS помогает использовать роботов как "пользователей" и многими другими способами.
Установка
Сборка
Соберите робота в минимальной конфигурации:
- Корпус
- ЦПУ
- ОЗУ
E2E-E
Если вы играете в Enigmatica 2: Expert - Extended, в модпаке есть предопределенный рецепт EEPROM. Найдите его в JEI и создайте. У него будет цветное свечение.
Если вы его создали, можете пропустить следующий шаг
Запись программы на EEPROM.Запись программы на EEPROM
Вам понадобится рабочий компьютер OC для записи BIOS. Смотрите этот учебник чтобы собрать ваш первый компьютер.
-
Скачайте файл из интернета (требуется
), запустите из командной строки:
wget https://raw.githubusercontent.com/Krutoy242/lostuser/main/lostuser.min.lua- Чтобы записать на существующий EEPROM, запустите:
flash -q lostuser.min.lua LostUserВставка в робота
Возьмите EEPROM из корпуса компьютера и вставьте его в робота.
Использование
Программируйте робота, переименовывая его. Переименуйте робота на
или с помощью
.
Назовите вашего робота
robot.use(3), поставьте его на землю, включите и смотрите, как он кликает блоки перед собой.
Синтаксис
Кратко
Если вы не хотите изучать Lua и вам нужно, чтобы робот кликал правой/левой кнопкой мыши, вот несколько простых имен для робота и результат:
-
robot.use(3)- Робот будет кликать правой кнопкой мыши по блоку перед собой. -
robot.swing(3)- Робот будет махать мечом или ломать блок перед собой.
Операторы и выражения
Выполнение
Робот будет выполнять свое имя как код Lua в цикле
while true.Код может быть выполнен в любом варианте -
операториливыражение, но все равно должен следовать правилам потока кода Lua.Это оператор
sleep(1)Это выражение
1, sleep(1)Комбинирование оператора и выражения
a = robot.move(3) return a and robot.use(0)Возврат
Если выражение возвращает одну или несколько функций, они будут выполнены рекурсивно.
Обратите внимание, что все возвращаемые значения рассчитываются сначала, и только потом будут вызваны функции.
Вызов
robot.use(3), а затемsleep()function() return sleep end, robot.use(3)Глобальные переменные
- Все компоненты доступны как глобальные переменные.
- Компоненты сортируются естественным образом и добавляются в глобальные переменные по первой большой букве.
C => computer E => eeprom I => inventory_controller R => robot T => trading ...Дополнительные глобальные переменные:
-
i- текущий индекс цикла, начиная с 0.Вы можете добавить число после
i, чтобы получить его по модулю +1.i16 = i % 16 + 1 -
sleep(seconds: number = 1) -
write(...)- ошибка с сериализованным выводом. -
api(shortName: string, obj?: table)- написать полное имя сокращения.
Сокращение
Поскольку имя робота или дрона может содержать только
64символа, указатели должны быть сокращены.Таким образом, вместо написания полного имени указателя, вы можете его сократить. Например, вместо написания
robot.use(3), вы можете написатьr.u(3)или дажеRu3.Правила сокращения:
-
Если ключ имеет точное не-nil совпадение, оно будет возвращено.
R.use(3)-Rэто глобальная переменная, представляющая компонентrobot. -
Сокращение должно содержать первую букву, а затем, по желанию, любое количество оставшихся букв.
tbl.unk => table.unpack t.u => table.unpack -
Если несколько имен имеют одинаковую первую букву, будет выбрано самое короткое, алфавитно отсортированное имя.
robot.s -- robot.slot robot.se -- robot.space robot.sel -- robot.select -
Большая первая буква с точкой
.может использоваться без точки.-- Те же указатели robot.use == R.use == Ruse == Ru -
Число в конце сокращения будет вызывать сокращение как функцию с этим числом в качестве первого аргумента.
Ru3 -- robot.use(3) s10 -- sleep(10)В то же время, если это таблица, а не функция, все ключи таблицы будут естественно отсортированы и возвращен
N-й элемент.R16 -- robot.selectСмотрите больше в Числовом Словаре.
-
Локальные переменные не могут быть сокращены.
local query = {len=4} q.l -- Исключение: q не определено query.l -- l не определено query.len -- 4 > ```
Lodash
_Специальная вспомогательная функция нижнего подчеркивания
_.Индексация
_-
Использование
_с числами_123Вернет новый список-массив с длиной числа. Если первая цифра0, таблица будет с нулевым индексом._8 -- возвращает {1,2,3,4,5,6,7,8} _08 -- возвращает {[0]=0,1,2,3,4,5,6,7} -
Использование
_со словами_abcСоздает функцию, которая будет записывать результат в переменнуюabc. Функция возвращает переданное значение. Обратите внимание, что_abcфункциональна._a(4) -- Записывает `4` в глобальную переменную `a`, возвращает 4 _a'Ru3' -- Записывает функцию, выполняющую `Ru3`, в глобальную переменную `a` _a^Ru -- Создает функцию, записывающую результат `Ru` в глобальную переменную `a` b._a^3 -- b.a = 3
Вызов
_-
Использование
_на строке Загрузит код внутри этой строки и вернет его как функцию. Вызов этой функции всегда безопасен для ошибок — если внутри произойдет исключение, функция просто вернетnil._'Rm,s2'()(0) -- вызывает `sleep(2),robot.move(0)`Обратите внимание, что в этом примере функция
_возвращает два значения — функциюrobot.moveи результатsleep(2). Только когда мы вызываем возвращенные значения во второй раз, выполняетсяrobot.move(0). -
Использование
_на таблице или функции Преобразует их в специальную таблицу_{}или функцию_''для использования с Функциональным Программированием.{1,2}^1 -- вызовет ошибку _{1,2}^1 -- вернет {1,1} (см. Функциональное Программирование)
Функциональное Программирование
Любая таблица или функция, которую вы можете получить из глобальной переменной, будет преобразована в специальную таблицу
_{}.Эта таблица улучшена дополнительными метаметодами операторов, которые помогают с функциональным стилем программирования.
Любая итерация или вызовы
pairs()на этих преобразованных таблицах будут выводить элементы в естественно отсортированном порядке.Операторы ведут себя по-разному в зависимости от левой и правой стороны оператора.
Обратите внимание, что когда обнаруживается
строка, она загружается и преобразуется в функцию по принципу_'fnc'.Приоритет
Приоритет операторов в Lua следует таблице ниже, от высшего к низшему приоритету:
-
^ -
унарные
not#-~ -
*///% -
+- -
.. -
<<>> -
& -
~ -
| -
<><=>=~=== -
and -
or
Map
^,+, или&^,+, и&операторы делают то же самое. Их три, только для управления приоритетом.-
Примечание¹:
^ассоциируется справа. Это означает, что сначала будет вычислена правая сторона. -
Примечание²: Вы также можете вызывать невызываемые таблицы.
t(x)то же самое, чтоt^x. Невызываемые таблицы — это таблицы без метатаблицы__call. Пример (mapt^f):_{1,2,3}'0' -- _{0,0,0}
Левая сторона Правая сторона Результат Таблица Функция Классическая карта
_{4,5,6}^f -- {f(4),f(5),f(6)}Таблица Выбор индексов
_{4,5,6}^{3,1} -- {6,4}Число, Булево значение Добавление значения в КОНЕЦ таблицы
_{1,[3]=3,a=6,[4]=4}^5 -- _{1,3=3,4=4,5=5,a=6}Функция Функция Композиция
f^g -- (...)=>f(g(...))Таблица Распаковка как аргументы
f^{1,2,3} -- f(1,2,3)Число, Булево значение Простой вызов
f^1 -- f(1)Число, Булево значение Таблица Получение по числовому или булевому индексу
2^_{4,5,6} -- 5Функция Не реализовано
Лямбда
-/|Левая сторона Правая сторона Результат Таблица Функция Фильтр, оставляет только значения, являющиеся Истинными
_{4,5,6,7}/'v%2' -- {5,7}Таблица Не реализовано
Число, Булево значение Удаление индекса
_3/2 -- {1=1,3=3}Функция Функция Обратная композиция
f/g -- (...)=>g(f(...))Таблица Простой вызов
f/R -- f(R)Число, Булево значение Композиция
f/1 -- (...)=>f(1,...)Число, Булево значение Таблица Получение по модулю
i/t -- t[i % #t + 1]Функция Вращающаяся композиция
2/f -- (...)=>f(..., 2)Цикл
~или*Левая сторона Правая сторона Результат Таблица Функция Не реализовано
Таблица Не реализовано
Число, Булево значение Не реализовано
Функция Функция Пока истинно, делай
f~g -- пока истинно(g(j++)) делай f(j)Таблица Не реализовано
Число, Булево значение Цикл for
f~n -- for j=1,TONUMBER(n) do f(j) endЧисло, Булево значение Таблица Не реализовано
Функция То же, что и
f~n, но без передачи индексаn~f -- for j=1,TONUMBER(n) do f() endУнарные операторы
Унарный оператор Объект Результат ~Функция Пока истинно, делай
~f -- повторять пока не истинно(f())Таблица Сглаживание таблицы, используя числовые индексы.
- Порядок элементов может быть разным
- Все ключи таблицы будут преобразованы в индексированные
- Только 1 уровень сглаживания
~_{1,{2,3},{4,a=5,b={6,c=7}}} -- {1,2,3,4,5,{6,c=7}}-Функция Создать функцию, результат которой будет инвертирован. Если результат
истинный, возвращает0. Возвращает1в противном случае.-- id здесь функция, возвращающая свой первый аргумент (-id)(0) -- 1 (-id)(4) -- 0 (- -id)(4) -- 1Таблица Обмен ключей и значений
-_{'a','b','c'} -- {a=1,b=2,c=3}#Функция Создать функцию, которая будет оборачивать свой результат в таблицу. Полезно для функций, возвращающих несколько значений.
-- Предположим, `f(n)` возвращает три значения - 2,3,n f&4 -- 2 #f&4 -- _{2,3,4}Истинные значения
Знач ение считается "истинным", если оно не является "ложным".
"Ложные" значения:
-
falseилиnil -
''(пустая строка) -
0(ноль) -
nan(не число,n ~= n) -
infили-inf(результат1/0или-1/0)
Макросы
В программе есть несколько предопределенных макросов - символов, которые будут заменены везде на другой текст.
! => '()' ⓐ => ' и ' ⓞ => ' или ' ⓝ => ' не ' ⓡ => ' вернуть ' ⒯ => '(истина)' ⒡ => '(ложь)'Примеры
-
Перемещение между двумя точками и выполнение их метки
Требуемые улучшения:
,
Имя дрона:
P=i/Nf300ⓡDm^Pp,s/1~'Dg0>1',_(Pl)-
Nf300: Выполнитьnavigation.findWaypoints(300). -
i/Nf300:i- индекс выполнения скрипта.i / table- "Получение по индексу модуля"t[i % #t + 1]. -
P=i/Nf300: Записать в глобальную переменнуюPразличные точки каждый цикл скрипта. -
ⓡ: будет заменено навернуть -
Dm^Pp: вызовdrone.move(table.unpack(P.position)). -
s/1~'Dg0>1'=>пока drone.getOffset() > 1 делать sleep(1). -
_(Pl): ЗагрузитьP.labelкак код Lua. Эта загруженная функция будет возвращена и выполнена.
Метки точек. Первая просто всасывает снизу, вторая итерирует по 4 слотам и сбрасывает вниз.
_'Dsk0'~4 Dsel-'Dd0'~4 -
-
Зигзаг + Использование вниз, полезно для ферм
Требуемые улучшения: нет
Имя робота:
m,t=_'Rm3,Ru0',Rtn/(i2>1)ⓡ~m,t!,_'m!,t!'!ⓞt/m-
m,t=_'Rm3,Ru0',Rtn/(i2>1): определить две функции для движения и поворота-
_'Rm3,Ru0': определить функциюRm3,Ru0, которая будет двигаться вперед и использовать инструмент вниз -
Rtn/(i2>1): это создает функцию, которая будет вызыватьRtn(robot.turn) с аргументомi2>1.i2- сокращение дляi%2+1
-
-
~m: Заставляет робота двигаться вперед, пока он не сможет двигаться. -
t!: просто поворачивает -
_'m!,t!'!ⓞt/m: Двигаться и поворачиваться. Если движение не удалось, повернуться и двигаться снова.
-
-
Торговый бот
Требуемые улучшения:
,
,
Имя робота:
Rsel-'Rd0'~RiS0,IsF/0~Igz0,Tg0'~tr'-
Rsel-'Rd0'~RiS0: Выбрать каждый слот и сбросить вниз-
'Rd0': это функция, которая будет вызыватьrobot.drop(0)при выполнении. -
RiS0: сокращение дляrobot.inventorySize(0). Обратите внимание, что эта функция не использует аргументы, поэтому мы можем вызвать ее с0 -
Rsel: сокращение дляrobot.select. Обратите внимание, что мы использовали оператор-, который такой же, как/, но имеет более низкий приоритет
-
-
IsF/0~Igz0: Для каждого слота инвентаря снизуinventory_controller.getInventorySize(0)вызватьinventory_controller.suckFromSlot(0, k) -
Tg0'~tr': Торговать всеми товарами.-
~tr: Вызыватьtrade()пока возвращает истину. Обратите внимание, что внутри этой функции все аргументы открыты как глобальные, поэтому мы можем получить доступ кtradeкак к глобальной переменной (на самом деле этоupvalue)
-
Есть другой вариант имени робота, более продвинутый. Он будет забирать только предметы, которые действительно требуются для торговли. Эта программа жестко запрограммирована для работы с внутренним и внешним инвентарем размером 16:
-- Торговать всем a=-~Tg0"_{g!}'n',~tr"ⓡ_16&R16-'Rd0'&IgI/0&'a[n]ⓐI8/0&k' -- Не продавать изумруды [id==388] a=-~Tg0'388^-g0ⓞ{g0.n,~tr}'ⓡ_16&R16-'Rd0'&IgI/0&'a[n]ⓐI8/0&k' -
-
Создатель рун
Требуемые улучшения:
,
Поместите ингредиенты в первые 6 слотов робота. Живой камень на 7-м, палочку на 8-м.
Имя робота:
_8/'Rsel^v,v==7ⓐ{s3,Rm1,Rd(3,1),Rm0}ⓞ{Ie!,Ru3,Ie!}'-
Rsel^v: Выбрать слот по очереди -
v==7ⓐ{s3,Rm1,Rd(3,1),Rm0}: если это 7-й слот с Живым камнем, подождать 3 секунды до завершения крафта, затем сбросить Камень сверху. -
Ie!,Ru3,Ie!: Для других слотов - просто кликнуть правой кнопкой мыши с предметом
-
-
Ферма одиночных деревьев
Требуемые улучшения:
,
Этот робот предназначен для использования с саженцами Forestry, которые обычно не могут быть поставлены как блоки, но требуют клика правой кнопкой мыши для посадки. Кроме того, роботу нужен неразрушимый Широкий Топор из TCon с чертой Глобальный Путешественник. Кроме того, мой топор имеет черту Удобрение - клик правой кнопкой мыши для удобрения. Поставьте робота на контейнер с саженцами.
Имя робота:
#(1|#Rdt&3)<6ⓐRsw/3-s/1-Rsk/0-Ie-Ru/3-IeⓞRu3,s-
(1|#Rdt&3): Обнаружить блок перед собой, выбрать второе возвращаемое значение - описание блока -
#()<6: хитрость, чтобы определить, является ли блок твердым -
Rsw/3-s/1: Срубить все дерево, подождать 1 секунду -
Rsk/0-Ie-Ru/3-Ie: Всосать саженец снизу, затем посадить его. Обратите внимание, чтоRskполучает одно значение отsleepвозврата -
Ru3,s: Удобрить саженец
-
-
Другие примеры
-
Круговой шахтер. Используя Молот с частью из Алумита (черта Глобальный Путешественник). Поставьте Робота под землю, поместите стак Блоков Угля в выбранный слот робота. Робот начнет кружить вокруг, добывая все на своем пути.
Требуемые улучшения:
Дополнительные улучшения:
,
Gi,_'Rm3,Rsw3'~i*2,Rtn⒯ -
Робот для сортировки дропа мобов. Берет снизу, предметы, подлежащие повреждению, вверх, остальные - вперед.
Требуемые улучшения:
,
Rd|3%2^(IsF(0,i%Igz0+1)ⓐIgSII!.mDⓞ2) -
Открыватель кошек. Берет 16 предметов перед собой, кликает их правой кнопкой мыши, затем сбрасывает инвентарь вверх.
Требуемые улучшения:
,
Rsk/3&16ⓐIe!,~_'Ru0',_16/Rc|Rsel/'Rd1' -
Компрессионный бот. Берет спереди, крафтит 3x3, затем сбрасывает назад.
Требуемые улучшения:
,
,
-(_16-Rc&12)|'Rd3'&Rsel,IsF/3/'_11/8/4&Rc!/9/RtT'|i81,Cc -
Бот для неразложимых предметов. Берет предмет перед собой только если они неразложимы и кладет их наверх. Если не может сбросить предмет наверх, толкает вверх и ставит блок.
Заполните все слоты робота, кроме 1. Слот 9 должен иметь новые инвентари для неразложимых предметов.
Требуемые улучшения:
,
,
(IgSI/3&_a^i1728ⓞ{}).mS^_{_'IsF/3&a,Rd1ⓞ{Pps1,Rsel9,Rp1,Rsel1}'}
-
Дополнительно
Ссылки
- Репозиторий с исходным кодом и readme
- Модпак, для которого был запрограммирован этот робот: Enigmatica 2: Expert - Extended
Старое описание:
Скрытый текстРоботы OC очень сложны в сборке и программировании.
С этим биосом робота можно программировать через переименование на наковальне.
Ссылка на английский Readme с большим количеством инфы.
Установка
Соберите робота минимальной конфигурации
- Корпус
- CPU
- RAM
(Кстати, в моем модпаке Enigmatica 2: Expert - Extended этот чип будет крафтиться, так что игрокам даже не нужен стационарный компьютер что бы пользоваться чипом.)
-
Скачайте программу из интернета:
wget https://gist.githubusercontent.com/Krutoy242/db63637d605c2c247bc95e939c7f7ddd/raw/lostuser.min.lua
-
Запишите прогу на чип:
flash -q lostuser.min.lua LostUser -
Вставьте чип в робота
Использование
Робот программируется путем его переименования. Можно использовать наковальню
или вот такой инструмент из мода
Integrated Dynamics.
Назовите своего Робота \3, поставьте на землю, включите и посмотрите, как он будет щелкать по блоку впереди.
Для тех кто заинтересовался, о синтаксисе программирования робота через имя можно посмотреть в англ. Readme.
Примеры
IC2 растения
Мы будем использовать робота для разведения культур Industrial Craft 2.
Для этого нужно посадить семена в шахматном порядке, а между ними поставить поперечные палочки. Робот должен бегать по грядке и нажимать правой кнопкой мыши с инструментом, чтобы собирать сорняки.
Имя такого робота будет \0ZZ
Видео во вложении.
Ferrous-Juniper ферма
А вот пример более сложной программы
?(y0)'E9nS18''^9/0s18|0'ZЭта программа:
- Выкидывает предметы из слотов 9-16 вниз
- Засасывает предметы в слоты 1-8 сверху
- Перемещается зигзагообразно, ломает блок под собой и ставит новый
Давайте ее разберем.
-
С начала идет условный оператор ?. Он принимает 3 аргумента:
1) Условие (y0),
2) Блок then 'E9nS18'
3) Блок else '^9/0s18|0' - Условие это программа y0, где y - сокращение команды inventory_controller.getInventorySize. Некоторые сокращения записаны в исходном коде.
- Блок then выполняет две программы. E9n - слить слоты с 9 по n вниз. S18 - набрать предметы сверху.
- Блок else выделяет 9 слот ^9, ломает блок под собой /0, выбирает первый не-пустой слот s18, устанавливает блок вниз |0.
- В самом конце проги стоит буква Z, которая означает Зигзагообразное движение.
Фидбэк
Если кому то понравилась идея, пишите как можно улучшить.
Особенно интересно, какие операторы стоит добавить в заранее записанные сокращения, а в каких сокращениях лучше сменить букву.
Главный принцип - возможность писать сложные программы используя всего несколько символов.
-
9
-
1
-
1
-
1
-
1 минуту назад, prop сказал:Статью не читал. Лямбда-исчесления знаю ужасно. Знаю только что f(1)(2)(3) - это лямбда.
-
1
-
-
Нашел баг.
test( "true/false arguments", "a:true b:false c:c", function() f = L( function(a, b, c) return 'a:' .. tostring(a) .. ' b:' .. tostring(b) .. ' c:' .. tostring(c) end, 'a', 'b', 'c' ) return f(true)(false)() end ) -- [Failed] true/false arguments -- Expected: a:true b:false c:c -- Got: a:true b:b c:c
Тот самый случай, когда ты подумал "a and b or c" это настоящий условный оператор, а он подвел.
Но я знаю как исправить, нужно просто заменить на "==nil"
-
1
-
1
-
-
Я полностью удовлетворен! Спасибо за помощь!
P.S. Уже третий час пишу документацию по своему новому языку....
-
1
-

LostUser - простейший робот
в eeprom
Опубликовано:
Переписал README на русский язык.
Смотрите тут или в 0м сообщении: