PDA

Просмотр полной версии : парсинг текста или скрипты в боте


Elecktron
15.02.2013, 13:36
дорос мой бот до скриптов, ибо намертво зашитый функционал слишком не гибкий и давно уже не соответствует требованиям...

казалось бы - вполне хватит команд "а ля валкер" - ничего сложного вроде нет, вносим скрипт в Memo и запускаем.. но не тут то было!

в коде реализуем функции типа:
UseItem(id)
UseSkill(id)
MTL(x,y,z)

и дергать будем их из скрипта.
вопрос только в том, как распознать какую функцию и с каким параметром дернуть..

решение вида:
while (i<Memo1->Lines->Count)
{
c = 0;
opr = Memo1->Lines->Strings[i];
while (c<Memo1->Lines->Strings[i].Length())
{
c++;
if (opr[c] != '#')
{
if (opr[c] == 'M' && opr[c+1] == 'T' && opr[c+2] == 'L')
ShowMessage("MTL");
}
else
{
c = Memo1->Lines->Strings[i].Length();
ShowMessage("закоментированная строка");
}
}
i++;
}
действенно, но несколько не изящно и громоздко
когда количество скриптовых команд разрастется до 10+ можно будет в этом коде сломать не только голову...
к тому же могут возникнуть проблемы с параметрами, количество символов в которых может варьироваться.

гуглю не первый день, в выдаче странные результаты, местами мало относящиеся к моей теме.
использовать сторонние библиотеки и движки не вижу смысла, да нет желания прикручивать в Visual C++..

буду признателен за любые идеи и подсказки...

"нюхом чую", что решение где-то рядом, и совсем простое.. :)

n1ghtmare
15.02.2013, 15:39
Это какой язык? Судя по всему это c++ builder?

Zergatul
15.02.2013, 20:02
Можно заюзать простые рег експы для парсинга названия и всех параметров в удобный массив.

Пример на джаваскрипте (можно запустить в консоли браузера):

str = 'someFunc(1, 2, 3, "qq", true)'
str.match('^([a-zA-Z]+)\\((.+)\\)$')

Выдаст: ["someFunc(1, 2, 3, "qq", true)", "someFunc", "1, 2, 3, "qq", true"]

Дальше парсим параметры:
params = '1, 2, 3, "qq", true'
params.match(/([^,]+)+/g)
Результат:
["1", " 2", " 3", " "qq"", " true"]

n1ghtmare
15.02.2013, 21:58
Примерно так, а в памяти хранить пару { "имя в скрипте", указатель на реальную } А вообще я бы посоветовал lua.

Elecktron
15.02.2013, 22:41
Это какой язык? Судя по всему это c++ builder?

зря ты удалил свое сообщение, оно содержало достаточно много полезной информации.
да это c++ builder.
да конечный вариант будет на MS Visual C++

да я прекрасно понимаю что такие конструкции
if (opr[c] == 'M' && opr[c+1] == 'T' && opr[c+2] == 'L')
попадают под классификацию "быдлокод".
иначе бы я не задавал бы здесь вопросов, а сделал бы так и не морочил голову. в некоторых случаях такого более чем достаточно и нет смысла делать иначе.

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

C++ не имеет встроенной реализации работы с регулярными выражениями.
поэтому приходится "лепить"

в phx используется Pax Compiler. это избыточно, громоздко и писалось для delphi.

n1ghtmare
15.02.2013, 23:32
зря ты удалил свое сообщение, оно содержало достаточно много полезной информации.

Удалил потому что провтыкал с языком, увидел memo и сразу подумал что это delphi. :)
Но суть та же. Что мешает в builder'e использовать готовый движок (К примеру Lua, я его использую) ? Причем тут visual c++. Ведь движки как правило ничего кроме stl не используют. В билдере какой-то не такой stl?

Кстати никто не заставляет использовать регулярки, хотя тот же boost имеет реализацию регулярок. функция strstr (http://www.cplusplus.com/reference/cstring/strstr/?kw=strstr)
К примеру так:

if (strstr(line, "MTL(") == line) { ... }

Ищем подстроку, и если она находиться в начале строки то ура.

Это не лучший вариант, т.к. в строковых параметрах к примеру может быть название функции ну и т.п.

mira
19.02.2013, 15:25
используй имеющиеся скрипт движки. больше времени потратиш на изобретение велосипедов чем на бота.

SeregaZ
19.02.2013, 15:44
велосипеды - путь к более обширному понимаю того, что происходит. самый лучший путь к самообразванию.

Elecktron
19.02.2013, 18:57
велосипеды - путь к более обширному понимаю того, что происходит. самый лучший путь к самообразванию.
чем я собственно и занимаюсь :)
готовые скриптовые движки (типа PaxCompiler) громоздки и избыточны.
да и конкретно Pax не очень хорошо совмещается с MSVC++
у меня уже есть варианты обработки, но пока это обрывки набросков и мыслей у меня в голове...
когда оформится это все в рабочий (или не очень :)) код я обязательно выложу на суд общественности :)

Elecktron
23.02.2013, 04:37
вот что получилось в результате сбора кусочков мыслей и нескольких часов гугления:

while (i<Memo1->Lines->Count)
{
TStringList *WCount = new TStringList();
TSysCharSet Tws,Tcs;
Tcs<<'('<<')'<<','<<' '; // разделители
AnsiString s = Memo1->Lines->Strings[i];
ExtractStrings(Tcs,Tws,s.c_str(),WCount);

if(WCount->Strings[0] == "MTL")
{
ShowMessage("Moving to x:"+ WCount->Strings[1]+" y:"+WCount->Strings[2]+" z:"+WCount->Strings[3]);
}
else
if(WCount->Strings[0] == "UseItem")
{
ShowMessage("Use Item ID:"+ WCount->Strings[1]);
}
else
if(WCount->Strings[0] == "#")
{
ShowMessage("ignored line");
}
else
Label1->Caption = "Expression syntax on line "+IntToStr(i); //тут бы еще допилить прерывание выполнения...

i++;
delete WCount;
}

в бота еще не интегрировал.
нужно будет переписать на MSVC++ (бот на нем :)), добавить функционала и реализовать отправку соответствующих пакетов...

Antharas
23.02.2013, 06:03
Так он скрипт читать будет тупо текст или еще компилировать его в машинный код? Просто интересно, я не очень шарящий)

Elecktron
23.02.2013, 07:18
это не компилятор.
это скриптовый интерпритатор.
есть набор команд которые мы можем использовать: перемещение в точку с координатами, исползование предмета, использование скила, взятие в таргет, "ткнуть" диалог нпс итд итп...
а вот этим командам мы уже передаем свои параметры...
и последовательность мы тоже задаем.
вопрос только в красоте реализации и защищенности от "дурака", но в варианте "для себя" защитой от дурака можно пренебречь - сам сделал - сам себе "дурак" :)

Добавлено через 59 минут
и возвращаясь к вопросу "а что собственно из готового можно использовать?"
мелкое и ненапряжное, без ооп и тому подобных заморочей, понимающее конструкции "if", "for", "goto" итп, и с возможностью прописывания своих функций?
просто я как-то уже искал, и ничего вменяемого не нашел, потому и начал ваять свое...

Sinn3r
23.02.2013, 08:42
Elecktron, вот почитай туториал по lex/yacc, думаю собрать простенький скриптовый движок будет не сложно

n1ghtmare
23.02.2013, 14:24
и возвращаясь к вопросу "а что собственно из готового можно использовать?"
мелкое и ненапряжное, без ооп и тому подобных заморочей, понимающее конструкции "if", "for", "goto" итп, и с возможностью прописывания своих функций?
просто я как-то уже искал, и ничего вменяемого не нашел, потому и начал ваять свое...

Уже предлагал тебе Lua, в нем есть таблицы, есть некое подобие ООП, но никто не заставляет тебя его использовать. Регистрируешь нужные функции и вперед.

Elecktron
24.02.2013, 03:03
Elecktron, вот почитай туториал по lex/yacc, думаю собрать простенький скриптовый движок будет не сложно

погуглил, почитал... не помогло.. кроме назначения неясно ничего... :(

Уже предлагал тебе Lua, в нем есть таблицы, есть некое подобие ООП, но никто не заставляет тебя его использовать. Регистрируешь нужные функции и вперед.

а с луа вообще непонятно - как "это" использовать?
можно пример?

ингейм валкер использует int __cdecl _wcsicmp(const wchar_t *,const wchar_t *) в связке if-else для обработки скрипта...
а вот чем он "нарезает" строки я так и не нашел...

ffoxin
27.10.2013, 15:45
насколько я понял, у вас проблема с обработкой строк.

для сишных строк есть набор функций в <string.h> http://www.cplusplus.com/reference/cstring/

для плюсов стоит переходить на <string> http://www.cplusplus.com/reference/string/

все операции (сравнение строк, поиск подстроки) там реализованы.

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

чтобы не погружаться в работу с памятью ручками - используйте wstring и соответствующие методы - find, substr

для сишных же строк аналогичные функции - strchr/strstr, strcpy