mrbean27

Участник

Автор темы

Нужно искать примеры в чате, пример может быть длиной до 6-ти чисел включительно, также могут быть использованы рандомные цвета, порядок которых ты чисто физически не знаешь
Пример: Что-то там 53 + 73 * 9 / 23 Что-то там
Пример 2: Что-то там 5 + 1 — 6 + 4 / 2 + 8 Что-то там

Я написал такой говнокод:

function samp.onServerMessage(color,text) local plus = ‘[-+/*^]%d+’ local plus2 = ‘%s[-+/*^]%s%d+’ if text:match(‘%d+’..plus..plus..plus..plus..plus) or text:match(‘%d+’..plus..plus..plus..plus) or text:match(‘%d+’..plus..plus..plus) or text:match(‘%d+’..plus..plus) or text:match(‘%d+’..plus) then local message_chat = text:match((‘%d+’..plus..plus..plus..plus..plus)) or text:match((‘%d+’..plus..plus..plus..plus)) or text:match((‘%d+’..plus..plus..plus)) or text:match((‘%d+’..plus..plus)) or text:match((‘%d+’..plus)) local otvet = math.round(calc(message_chat),2) lua_thread.create(function() wait(math.random(0, 500)) sampSendChat(otvet) end) elseif text:match(‘%d+’..plus2..plus2..plus2..plus2..plus2) or text:match(‘%d+’..plus2..plus2..plus2..plus2) or text:match(‘%d+’..plus2..plus2..plus2) or text:match(‘%d+’..plus2..plus2) or text:match(‘%d+’..plus2) then local message_chat = text:match((‘%d+’..plus2..plus2..plus2..plus2..plus2)) or text:match((‘%d+’..plus2..plus2..plus2..plus2)) or text:match((‘%d+’..plus2..plus2..plus2)) or text:match((‘%d+’..plus2..plus2)) or text:match((‘%d+’..plus2)) local otvet = math.round(calc(message_chat),2) lua_thread.create(function() wait(math.random(0, 500)) sampSendChat(otvet) end) end end function calc(str) return assert(load(«return » .. str))() end

Мой говнокод решает такие примеры, но только если в нём используется только один цвет текста по типу:

ChatCalculator MINECRAFT | АВТОМАТИЧЕСКОЕ РЕШЕНИЕ ПРИМЕРОВ ИЗ ЧАТА


Что-то там 5+7+4+1+8 Что-то там

1. Как мне сделать поиск этих примеров без добавлений каждый раз этого чёртвого плюса, либо как сделать чтобы в примере могло быть неограниченное количество чисел?
2. Как игнорировать цвет текста в чате при поиске?

Источник: www.blast.hk

Бот для арифметической викторины в чате

Тут формат сообщения кастомный, ещё и сам пример в виде спецсимволов.

👀

hohserg

7,067 321 1,491
В чем проблема поменять мой код?)
Новая рандомная ава топовая) Ender’sMagic 1.4b — УРААА!))

Майнкрафт это моя жизнь

Таумкрафт 6 — ураа!
Пишу на Scala
Какая ирония: написание тутора позволяет понять тему лучше, чем его чтение
Test BB-code

tox1cozZ

aka Agravaine

8,429 597 2,870
Да тут придется почти все переписывать )

CumingSoon

Местный стендапер

1,635 12 267

Сообщения в некоторых плагинах, подобных моему, можно гибко изменять прямо в конфиге. Т.е. твоя штука на них просто не затригерится.
Обрати внимание на сообщение из вчерашней темы:

1588589789493-png.8619

Тут формат сообщения кастомный, ещё и сам пример в виде спецсимволов.

will0376

Токсичная личность

1,825 50 491

Такой код не поможет на крупных серверах. Ибо там стоит лаунчер, не позволяющий заливать своё(исключая dll иньекцию и другие баги лаунчеров.)
Лучше предоставь с лога лаунчера кусок этого текста?

Plasticable

291 14 156
В чем проблема поменять мой код?)
С учётом того, что он на эльфийском, действительно
придется почти все переписывать
Можно вытаскивать сообщения без форматирования.
Ибо там стоит лаунчер, не позволяющий заливать своё

Я делал так: отдельной прогой парсил лог клиента, в котором были все входящие сообщения, находил и решал примеры, ответ выводил в консольку, которая была на соседнем монике. Всё, что мне оставалось — вписать число в чат.

Последнее редактирование: 5 Май 2020

👀

fukkivdan

1,139 26 150

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

вполне юзабельно кстати

tox1cozZ

aka Agravaine

8,429 597 2,870
отдельной прогой парсил лог клиента, в котором были все входящие сообщения,

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

Plasticable

291 14 156

👀

hohserg

7,067 321 1,491

не решит 1-1, потому что ты у минуса пробелы учитываешь. Алсо, такое лучше адекватно парсить, иначе сломается на (500 + 0) * 2

Как, если я юзаю парсинг через js интерпретатор? Это такой прикол js?
Новая рандомная ава топовая) Ender’sMagic 1.4b — УРААА!))

Таумкрафт 6 — ураа!
Пишу на Scala
Какая ирония: написание тутора позволяет понять тему лучше, чем его чтение
Test BB-code

tox1cozZ

aka Agravaine

8,429 597 2,870
Для сложных выражений имхо лучше юзать exp4j

hohserg

7,067 321 1,491

А вообще, я юзал этот кусок на одном проекте и вроде не возникало проблем. Там были в том числе задания с вычитанием

Читайте также:  Кто такой кабан и добрый из Майнкрафта

Новая рандомная ава топовая) Ender’sMagic 1.4b — УРААА!))

Таумкрафт 6 — ураа!
Пишу на Scala
Какая ирония: написание тутора позволяет понять тему лучше, чем его чтение
Test BB-code

CumingSoon

Местный стендапер

1,635 12 267
Как, если я юзаю парсинг через js интерпретатор? Это такой прикол js?

Я не весь код посмотрел, соре
Тут, в общем-то, просто адекватный поиск выражений стоит сделать. Ну или хотя бы учесть случа 2-2(где минус без пробелов)

hohserg

7,067 321 1,491

В чем смысл? JS ведь все сделает, достаточно только выделить арифметическое выражение из сообщения.
Делать это нужно путем поиска окружающего выражения текста, а не путем поиска самого выражения. Ибо иначе вас спалят просто написал в чат «Тест на читера 1+2+3».

Новая рандомная ава топовая) Ender’sMagic 1.4b — УРААА!))

Таумкрафт 6 — ураа!
Пишу на Scala
Какая ирония: написание тутора позволяет понять тему лучше, чем его чтение
Test BB-code

MJaroslav

1,188 37 227

Не встречал викторин где были примеры отличные от + или -, всегда решал пример по ходу ввода его ответа (слева направо да). Но вот если примеры сложные, то круто, да.

Заказы не принимаю. Оффлайн с 12.2022 до 12.2023.

CumingSoon

Местный стендапер

1,635 12 267

necauqua

когда-то был anti344

Администратор

1,154 22 154

Написать калькулятор на jparsec занимает один экран декларативного кода, какой javascript eval, вы шо, ебобо?)

рашка-какашка, ахах, вау, roasted.. кринжовая автократия ответственная за 80% мировой нестабильности из-за каких-то супер-идиотских амбиций, лол, зачем?.

Меня CMTV (так же известный в узких кругах как СЬЕМ) не удаляет из админов несмотря на появление тут раз в несколько месяцев в лучшем случае, приятно

hohserg

7,067 321 1,491
jparsec занимает один экран декларативного кода
А js занимает одну строку. По-моему, выбор очевиден))
Новая рандомная ава топовая) Ender’sMagic 1.4b — УРААА!))

Таумкрафт 6 — ураа!
Пишу на Scala
Какая ирония: написание тутора позволяет понять тему лучше, чем его чтение
Test BB-code

necauqua

когда-то был anti344

Администратор

1,154 22 154

Окей, плюсы js: занимает одну строку
Минусы js: инъекции, поднятие целого движка js, все те мемные проблемки js с операторами и так далее

Минусы своего декларативного парсера: занимает аж экран кода, и то это у меня тогда там ещё AST было, если тупо при парсинге сразу считать то это строчек 10-15.
Плюсы своего декларативного парсера: чёткий и ясный синтаксис, который ты сам описал, не больше, не меньше, намного-намного быстрее, банально правильнее, и уж точно никаких странностей js или инъекций, кек.

И ок, если тут в твоём случае надо просто по-быстрому грязно посчитать экспрешн, не парясь, то можно и так, но говорить при этом «выбор очевиден» — ну ты и людишка после этого конечно.

рашка-какашка, ахах, вау, roasted.. кринжовая автократия ответственная за 80% мировой нестабильности из-за каких-то супер-идиотских амбиций, лол, зачем?.

Меня CMTV (так же известный в узких кругах как СЬЕМ) не удаляет из админов несмотря на появление тут раз в несколько месяцев в лучшем случае, приятно

Источник: forum.mcmodding.ru

Математика в Майнкрафте

eu_tomat

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

Весь код охранной системы я разбирать не буду, сосредоточусь только на математике.

Остаток от деления

Начнем с такого фрагмента:

local function kostil(x) while true do if x>=360 then x = x — 360 elseif x

По названию функции видно, что автор осознавал ущербность этого кода, но лучшего решения не знал или забыл. Разберемся, что делает этот код. В цикле вычитает 360 из аргумента, если он больше или равен 360, или добавляет 360, если меньше нуля. А по сути, приводит значение угла к диапазону [0,360). Зачем это делается?

Читайте также:  Как в Майнкрафте разделить вещи

Ведь, например, углы и -90˚ и 270˚ указывают одинаковое направление. Сколько бы полных оборотов (360˚) в какую бы сторону мы не совершили, направление от этого не изменится.

Тем не менее турель из OpenSecurity не принимает угол, выходящий за границы диапазона [0..360]. Приведение угла к нужному диапазону называют нормализацией. Угол можно нормализовать и в других диапазонах с полным углом, например [-180,+180]. Но наша турель требует диапазон [0,360]. Как же эффективно произвести нормализацию?

Лучшим решением является операция взятия остатка от деления. Заглянем в справочник:

a % b == a — math.floor(a/b)*b

Не сложно увидеть, что a % b дает нам ровно тот же результат, что и костыль qwertyMAN’а, но код сильно сократился и стал выполняться быстрее. qwertyMAN с этого костыля быстро спрыгнул, и в следующей версии упростил свой код, но поверь мне, брат, на форуме есть много таких костылей, и калеки не спешат с них слезать.
Вот, например, фрагмент кода, до которого я уже давно хотел докопаться. Код слишком длинный не только для своего функционала, но и для этой статьи, поэтому я спрячу его в спойлер:

function smartTurnLeft() robot.turnLeft() if direct==’N’ then direct=’W’ elseif direct==’W’ then direct=’S’ elseif direct==’S’ then direct=’E’ elseif direct==’E’ then direct=’N’ endend function smartTurnRight() robot.turnRight() if direct==’N’ then direct=’E’ elseif direct==’E’ then direct=’S’ elseif direct==’S’ then direct=’W’ elseif direct==’W’ then direct=’N’ endend function smartTurnAround() robot.turnAround() if direct==’N’ then direct=’S’ elseif direct==’W’ then direct=’E’ elseif direct==’S’ then direct=’N’ elseif direct==’E’ then direct=’W’ endend

Можно ли этот код упростить? Легко. Для начала заменим строки числами, например, по такой схеме: N=0; W=1; S=2; E=3
После чего становится очевидным такое решение:

function smartTurnLeft() robot.turnLeft(); N=(N+1)%4; endfunction smartTurnRight() robot.turnRight(); N=(N-1)%4; endfunction smartTurnAround() robot.turnAround(); N=(N+2)%4; end

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

Тригонометрия

Теперь взгляни на эту функцию

local function pointer(x,y,z) local distXY = math.sqrt(x^2+z^2) local distDY = math.sqrt(y^2+distXY^2) local outX = math.deg(math.acos(x/distXY))+90 local outY = 90-math.deg(math.acos(y/distDY)) if z

Что она делает? Понять не сложно: вычисляет угловые координаты цели: азимут и угол места в градусах.
Что тут не так?
1) присутствует acos с последующим добавлением/вычитанием 90˚, хотя известно, что и синус и косинус при добавлении/вычитании 90˚ преобразуются друг в друга. На этом я задерживаться не буду, формулы и их вывод есть в любом учебнике.
2) использование только asin или только acos тоже является не лучшей идеей: asin имеет низкое разрешение по углу в окрестности +/-90˚, а acos – в области 0 ˚и 180˚, снижая точность наведения, и для ее повышения потребуется использовать asin в окрестностях 0 ˚и 180˚ и acos в окрестности +/-90˚.
3) вычисление синусов и косинусов требует вычисления расстояния до цели r=sqrt(x*x+z*z), а, например, вычисление тангенса не требует.
4) область значений asin, acos и atan не покрывает полный оборот в 360˚, поэтому приходится прибегать к дополнительным вычислениям, как, например, это сделал автор: if z5) не сошелся свет клином на всем известных со школы синусах, косинусах и тангенсах. Уделив несколько минут чтению списка математических функций, можно обнаружить такую красоту:

math.atan2(x, y)
Возвращает арктангенс x/y (в радианах), но использует знаки обоих параметров для вычисления «четверти» на плоскости. (Также корректно обрабатывает случай когда y равен нулю.)

Читайте также:  Как в Майнкрафте переместиться к игроку

В геометрии об этом не рассказывают, но такая функция имеется в стандартной библиотеке, пожалуй, любого высокоуровневого языка программирования. С ее помощью мы находим азимут цели единственной строкой azimuth=math.atan2(x, -z) . Осталось только выполнить преобразование в градусы, да скорректировать возвращаемый диапазон углов c [-180,+180] на принимаемый турелью [0..360], с чем мы уже разобрались.

Теперь надо правильно заполнить аргументы функции atan2. Для этого приведем всё, что у нас имеется, к картинке из школьного учебника.

Во-первых, на картинках в школьном учебнике угол растет при повороте от оси X, к оси Y, и тангенс угла вычисляется как tg(α) = y/x.
В справочнике же к atan2 указаны аргументы atan2(x, y) для вычисления арктангенса x/y. То есть, нам следует поменять аргументы местами. Имеем: math.atan2(y, x)

blogentry-13296-0-64746300-1456004244_thumb.png

Теперь разберемся с координатами мира Майнкрафта, положением турели, и тоже приведем их к картинке из школьного учебника. Сначала нарисуем координаты Майнкрафта при обращении лицом на север, вид сверху. Ось X направлена на восток, ось Z – на юг. Азимут поворота турели отсчитывается от северного направления по часовой стрелке.

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

X, Z – координаты мира Майнкрафта;
R – вектор на цель;
α – небольшой положительный угол между нулевым положением турели и вектором на цель.

На первом рисунке изображены исходные координаты майна и поворота турели.
На втором – поворот рисунка на 90˚ по часовой стрелке.
На третьем – отражение рисунка по вертикали (как бы взгляд на плоскость карты не сверху, а снизу, из-под земли). В принципе, можно было бы обойтись без второго рисунка, отразив первый по диагонали, идущей из правого верхнего угла, но для улучшения восприятия я привел оба рисунка.
На четвертом рисунке выполняется инверсия оси Z.

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

Все совершённые преобразования были нужны лишь для наглядности, и из них можно вывести более простое правило. Тригонометрия из школьного учебника основана на росте угла от оси X к оси Y. Но аналогичные формулы применимы при росте угла от оси -Z к оси X при соответствующих заменах в формулах. То есть, надо всего лишь знать от какой оси начинается рост угла и к какой оси происходит движение.

В результате выполненных преобразований ты можешь легко заметить, что координаты из учебника (x,y) соответствуют координатам Майнкрафта (-z,x).
В нашем случае:

sin(α) = y/r → sin(α) = x/rcos(α) = x/r → cos(α) = -z/rtg(α) = y/x → tg(α) = x/-z

Таким образом наш код приобретает вид: math.atan2(x, -z)
Осталось лишь преобразовать радианы в градусы и нормализовать их в диапазоне [0..360]: azimuth=math.deg(math.atan2(x,-z))%360

blogentry-13296-0-72447800-1456004250_thumb.png

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

Теперь тело функции, вычисляющей углы направления турели, умещается в три строки.

local azimuth=math.deg(math.atan2(x,-z))%360local elevation=math.deg(math.atan2(y,math.sqrt(x*x+z*z)))return azimuth, elevation

Или даже в одну, если не создавать промежуточные переменные и сразу возвращать результат.

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

Нравится

  • 13

Источник: computercraft.ru