Forum.iFiction.Ru

iFiction.Ru · ifHub · FAQ · IFWiki · QSP · URQ · INSTEAD · AXMA

форум об interactive fiction, текстовых приключенческих играх и всём таком...

Вы не зашли.

0    0    #1
05.12.2007 12:55

Flint
Участник
Зарегистрирован: 06.09.2007
Сообщений: 148

---

Универсальный spellchecker для RTADS

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

Интерфейс всех парсерных игр основан на вводе текста, причем количество введенного игроком текста за всю игру может быть весьма существенным. Естественно, не обходится без ошибок. «К сожалению, слово "деференциал" мне неизвестно.» Довольно странным выглядит то, что эта проблема никак не решается в этой абсолютно текстовой среде, где, вроде бы, сам бог велел (а ведь сейчас проверку орфографии встраивают даже в браузеры), тем более, что никаких словарей для проверки таскать за собой не надо – словарь, вот ведь он, заботливо объявленный автором в самой игре!

Поэтому я решил написать нечто вроде spellchecker для RTADS.
Он исправляет опечатки следующих типов:
1) пропустили букву
>о холдильник

2) набрали лишнюю букву
>о холодлильник

3) перепутали буквы местами (частенько случается при наборе)
>о холдоильник

4) ошиблись в букве
>о халодильник

После того, как вы нажмете Энтер, на экране, вместо раздражающего

«К сожалению, слово "халодильник" мне неизвестно.»

вы увидите

Возможно, вы имели в виду «холодильник».

Высокий белый холодильник. На боковую стенку налеплен магнит в виде головы панды (довольно дурацкий, верно?).


Мой spellchecker исправляет только одну ошибку на слово (т.е. «халодильник» он исправит, а «халадильник» уже нет). Это связано с объемом вычислений. Для слова из 7 букв выполняется 478 проверок на одну ошибку, соответственно, для проверки на 2 ошибки необходимо производить 478^2 = 228484 проверок, что конкретно затормаживает игру. К тому же, по статистике Google, из всех ошибок при вводе ошибки в одну букву составляют более 90% случаев, так что большинство опечаток мой spellchecker исправит.

Спелчекер универсален – он использует активный словарь текущей игры, обеспечивая тем самым 100% релевантность исправлений и минимум ложных срабатываний :-).

Чтобы подключить spellchecker к вашей игре на RTADS, сделайте следующее (процесс описан для файлов 24 релиза библиотек, но, скорее всего, заработает и на более ранних):

1. Откройте файл advr.t, найдите там функцию preparse и в самый ее конец, но перед “return comStr;” воткните
global.prevCommand := comStr;

2. Откройте файл erroru.t и в самый конец файла добавьте

parseErrorParam: function(errornum, string, ...)
{
    local correct, pos, newstr;
   
    if (errornum != 2)
        return parseError(errornum, string);
   
    correct := spellcheck(getarg(3));
    if (correct)
    {
        pos := reSearch(getarg(3), global.prevCommand);
        newstr := substr(global.prevCommand, 1, pos[1] - 1) + correct + substr(global.prevCommand, pos[1] + pos[2], length(global.prevCommand));
       
        "Возможно, вы имели в виду <b>&laquo;<<correct>>&raquo;</b>.<br><br>";
        parserReplaceCommand(newstr);
    }
   
    return parseError(errornum, string);
}

spellcheck: function(word)
{
    local ruslet := 'абвгдежзиклмнопрстуфхцчшщьыъэюя';
    local englet := 'abcdefghijklmnopqrstuvwxyz';
    local curlet := ruslet;
    local i, j;
   
    local variants = [];
    local found;
   
    //узнаем, английский ли это текст или нет
    for (i := 1; i <= length(word); i++)
    {
        for (j := 1; j <= length(englet); j++)
        {
            if (substr(word, i, 1) = substr(englet, j, 1))
            {
                curlet := englet;
                goto next;
            }
        }
    }
    next: ;
   
    //пропущенные буквы
    for (i := 1; i <= length(curlet); i++)
    {
        for (j := 0; j <= length(word); j++)
        {
            variants += substr(word, 1, j) + substr(curlet, i, 1) + substr(word, j + 1, length(word));
        }
    }
   
    //лишние буквы
    for (i := 0; i < length(word); i++)
    {
        variants += substr(word, 1, i) + substr(word, i + 2, length(word));
    }
   
   
    //неправильные буквы
    for (i := 1; i <= length(curlet); i++)
    {
        for (j := 0; j < length(word); j++)
        {
            variants += substr(word, 1, j) + substr(curlet, i, 1) + substr(word, j + 2, length(word));
        }
    }
   
    //перепутанные местами буквы
    for (i := 0; i < length(word) - 1; i++)
    {
        variants += substr(word, 1, i) + substr(word, i + 2, 1) + substr(word, i + 1, 1) + substr(word, i + 3, length(word));
    }
   

    for (i := 1; i <= length(variants); i++)
    {
        found := parserDictLookup([] + variants[i], [PRSTYP_NOUN]);
        if ( length(found) > 0)
            return variants[i];
    }
   
    for (i := 1; i <= length(variants); i++)
    {
        found := parserDictLookup([] + variants[i], [PRSTYP_VERB]);
        if ( length(found) > 0)
            return variants[i];
    }

    for (i := 1; i <= length(variants); i++)
    {
        found := parserDictLookup([] + variants[i], [PRSTYP_ADJ]);
        if ( length(found) > 0)
            return variants[i];
    }
   
    return nil;
}

Все! Компилируйте игру и можете пробовать.

Из недостатков спелчекера стоит отметить то, что он не занимается подбором форм слов, поэтому возможно неграмотное с точки зрения русского языка исправление написания, например «осмотреть сантехникв» (хотели написать «осмотреть сантехника») будет исправлено на «осмотреть сантехник». К сожалению, это никак не исправить.

Просьба протестировать работу на имеющихся у вас проектах RTADS. Пожелания и предложения приветствуются.

И напоследок, может кто-нибудь знает, как убрать вывод сообщения [TADS-1014: 'abort' statement executed] при каждом вызове функции parserReplaceCommand?

RTADS – лучшая платформа!

Неактивен

0    0    #2
05.12.2007 17:50

- VampirE -
Участник (+3)
Зарегистрирован: 22.06.2006
Сообщений: 101

Re: Универсальный spellchecker для RTADS

Почитал код.

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

Правда, я не в курсе различает ли тадс "а" нашу, от "а" латинской.

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

А так очень хорошо. smile

Отредактировано - VampirE - (05.12.2007 17:51)

Неактивен

Powered by PunBB
© copyright 2001–2024 iFiction.Ru