Як слід проаналізувати введення користувачів у текстову пригодницьку гру?


17

Розбір команд користувача в текстовій пригоді - це спектр від простого пригоди Adventure "піти на північ" до деяких розумно розумних в hhgttg .

Я, здається, пам’ятаю, як читав приємні роботи в комп’ютерних журналах ще в 80-х, але зараз я не знаходжу майже нічого в мережі, окрім короткого реферату Вікіпедії .

Як би ти це зробив?


Оновлення : Я пішов з найпростішим можливим підходом у моїй статті Ludum Dare .


3
Чи є певна проблема, яку ви намагаєтеся вирішити?
Тревор Пауелл

@TrevorPowell розглядає можливість зробити маленьку текстову пригоду для розваги, і просто хочу ознайомити себе з "сучасним мистецтвом", а не просто зануритися і вирішити його, як це все
Буде

1
Використовуйте Inform ; це найкраща стратегія, яку ви могли використовувати. В даний час практично немає причин кодувати текстову пригоду.
Ніколь Болас

@NicolBolas, якщо не наблизиться Людум Даре? ;)
Will

1
Це не стільки дефамістично, скільки прагматично. Перейти до всіх методів розширеного аналізу тексту (крім очевидних речей, які кожен може придумати), ймовірно, виходить за рамки однозначної відповіді.
Тетрад

Відповіді:


10

Ви шукали в спільноті інтерактивної художньої літератури? Вони все ще пишуть парсери, а деякі намагаються просунути конверт, застосовуючи нові методи, такі як обробка природного мови.

Дивіться, наприклад, це посилання для статей, що описують підходи, що використовуються:

http://ifwiki.org/index.php/Past_raif_topics:_Development:_part_2#Parsing


4
Ага, "текстові пригоди" стають "інтерактивною вигадкою" і раптом її набагато більш гуглиться! Хто б міг подумати, що це навіть змінить ім'я, оскільки я грав його? :) Тим не менше, дивлячись на ці результати, і насправді не дуже сумно пояснюється
Буде

9

Термін, який ви хочете, - це "обробка природним мовою", або NLP. Однак майте на увазі, що формальні методи розроблені для того, щоб спробувати і зрозуміти тексти реального світу, тоді як вам зазвичай потрібне лише те, що працює для обмеженого набору вашої природної мови.

Зазвичай ви можете почати з простої граматики та лексики, а потім написати парсер для цього. Граматика може бути чимось простою, як це:

sentence = verb [preposition] object
verb = "get" | "go" | "look" | "examine"
preposition = "above" | "below"
object = ["the"] [adjective] noun
adjective = "big" | "green"
noun = "north" | "south" | "east" | "west" | "house" | "dog"

Вищенаведений варіант є формою Backus-Naur, стандартним способом представлення граматик. У будь-якому випадку, ви можете використовувати генератор парсера для створення коду для розбору цієї граматики або написати свій власний досить легко, якщо ваша мова має гідну обробку рядків. (Знайдіть «рекурсивні аналізатори спуску», які використовують одну функцію для кожного рядка граматики.)

Після розбору, ви можете розібратися, якщо пропозиція має сенс - "піти на північ" може мати сенс, але "отримати зелену північ" не має. Ви можете вирішити це двома способами; зробіть граматику більш офіційною (наприклад, мають різні типи дієслів, які є дійсними лише для певних типів іменника) або перевірте іменники проти дієслова. Перший спосіб може допомогти вам видавати кращі повідомлення про помилки гравцеві, але завжди потрібно робити другу до певної міри, як завжди потрібно перевіряти контекст - наприклад. "взяти зелений ключ" є граматично правильним та синтаксично правильним, але все ж потрібно перевірити наявність зеленого ключа.

Врешті-решт ваша програма закінчується перевіреною командою з усіма перевіреними різними частинами; то це просто виклик правильної функції з аргументами для виконання дії.


6

Сучасним для створення текстових пригод сьогодні є використання Inform 7 . Інформація 7 джерела читає "як англійська мова" так само, як ігри на основі інформації дозволяють вам "писати англійською мовою". Наприклад, із бронзи Емілі Шорт :

У речі є текст, який називається запахом. Аромат речі - зазвичай "нічого".
Правило блочного запаху не вказано в жодній книзі правил.
Виконайте
    запах чогось: скажіть "Від [іменника] ви відчуваєте запах [запах іменника]".
Замість того, щоб пахнути кімнатою:
    якщо гравець може доторкнутися до запашної речі, скажіть "Ви відчуваєте запах [список ароматних речей, до яких може торкнутися гравець].";
    інакше кажіть "Місце блаженно не має запаху".

Аналізатор Inform 7 тісно інтегрований з IDE Inform 7, і весь вихідний код ще не доступний для вивчення:


5

Два найкращих поточних джерела для навчання створення текстового синтаксичного аналізатора - це (як уже згадувалося) спільнота ІФ та грязьке співтовариство. Якщо ви шукаєте такі основні форуми (Intfiction.org/forum, група новин rec.arts.int-fiction, грязьовий коннектор, мудбайти, мудлаб, сайти з грязьовими грязями), ви знайдете кілька відповідей, але якщо ви просто шукаєте для статей я б рекомендував пояснення Річарда Бартла про аналізатор у MUD II:

http://www.mud.co.uk/richard/commpars.htm

І це пояснення на rec.arts.int-fiction:

http://groups.google.com/group/rec.arts.int-fiction/msg/f545963efb72ec7b?dmode=source

Ніяка неповага не означала інших відповідей, але створення граматики CF або використання BNF не є рішенням цієї проблеми. Це не означає, що це не може бути вирішенням іншої проблеми, тобто створення більш досконалого розбору природних мов, але це предмет значних досліджень, а не ІМО в рамках текстової авантюри.


4

На моєму першому курсі в університеті ми зробили пригодницьку гру в Prolog, і для введення користувача нам довелося використовувати певну граматику пункту чи DCG. Див. Http://www.amzi.com/manuals/amzi/pro/ref_dcg.htm#DCGCommandLanguage для прикладу використання його як мови команд. Це здавалося принциповим (все-таки це було універсалом) та гнучким підходом у той час.


1

Вам потрібно визначити доменну мову, яка є усіма правильними реченнями у вашій грі. З цією метою ви повинні визначити граматику для своєї мови (словниковий запас та синтаксис). Тип граматики, яка вам потрібна, - це контекстна граматика, яка є безкоштовною, і є інструменти, які автоматично генерують аналізатор, починаючи з синтетичного опису граматики, наприклад ANTLR (www.antlr.org). Аналізатор лише перевіряє, чи є речення правильним чи ні, і виробляє Анотаційне синтаксичне дерево (AST) речення, яке є навігаційним поданням речення, де кожне слово має ту роль, яку ви вказали у граматиці. За допомогою навігації по AST ви повинні додати код, який оцінює, що таке семантика кожного слова, граючи цю роль щодо інших слів у реченні, і перевірити, чи правильна семантика.

Наприклад, речення "Камінь їсть людину" синтаксично правильне, але не обов'язково семантично правильне (якщо тільки у вашому світі камені, можливо, чарівні камені, можуть їсти чоловіки).

Якщо також семантика правильна, ви можете, наприклад, змінити світ відповідно до неї. Це може змінити контекст, і тому одне і те ж речення вже не може бути семантично правильним (наприклад, не можна було їсти людину)


1

Я використовував двигун Tads3 (www.tads3.org) для деяких текстових пригод, які я написав. Це більше для комп'ютерних програмістів, але дуже потужна мова. Якщо ви програміст, Tads3 буде набагато простіше кодувати речі швидше, ніж Inform7, яким я користувався і раніше. Проблема з програмою Inform7 для програмістів така ж відома, як і «здогадайся дієслова» для гравців текстових пригод, тому що якщо ти не пишеш свої речення ДУЖЕ ретельно, ти збираєшся зламати гру. Якщо у вас є терпіння зробити це, ви можете легко записати аналізатор на Java, використовуючи клас Tokenizer. Приклад Я написав, використовуючи глобальний JTextArea та глобальний масив String []. Він викреслює небажані символи, за винятком листів AZ та 0-9, а також знака питання (для ярлика команди "help"):

// put these as global variables just after your main class definition
public static String[] parsed = new String[100];
// outputArea should be a non-editable JTextArea to display our results
JTextArea outputArea = new JTextArea();
/*
 * parserArea is the JTextBox used to grab input
 * and be sure to MAKE sure somewhere to add a 
 * java.awt.event.KeyListener on it somewhere where
 * you initialize all your variables and setup the
 * constraints settings for your JTextBox's.
 * The KeyListener method should listen for the ENTER key 
 * being pressed and then call our parseText() method below.
 */
JTextArea parserArea = new JTextArea();

public void parseText(){
    String s0 = parserArea.getText();// parserArea is our global JTextBox
    s0 = s0.replace(',',' ');
    s0 = s0.replaceAll("[^a-zA-Z0-9? ]","");
    // reset parserArea back to a clean starting state
    parserArea.setCaretPosition(0);
    parserArea.setText("");
    // erase what had been parsed before and also make sure no nulls found
    for(int i=0;i < parsed.length; i++){
      parsed[i] = "";
    }
    // split the string s0 to array words by breaking them up between spaces
    StringTokenizer tok = new StringTokenizer(s0, " ");
    // use tokenizer tok and dump the tokens into array: parsed[]
    int iCount = 0;
    if(tok.countTokens() > 0){
      while(tok.hasMoreElements()){
        try{
          parsed[iCount] = tok.nextElement().toString();
          if(parsed[iCount] != null && parsed[iCount].length()>1){
            // if a word ENDS in ? then strip it off
            parsed[iCount] = parsed[iCount].replaceAll("[^a-zA-Z0-9 ]","");
           }
        }catch(Exception e){
          e.printStackTrace();
        }
          iCount++;
        }


      /*
       * handle simple help or ? command.
       * parsed[0] is our first word... parsed[1] the second, etc.
       * we can use iCount from above as needed to see how many...
       * ...words got found.
       */
      if(parsed[0].equalsIgnoreCase("?") || 
        parsed[0].equalsIgnoreCase("help")){
          outputArea.setText("");// erase the output "screen"
          outputArea.append("\nPut help code in here...\n");
        }
      }

      // handle other noun and verb checks of parsed[] array in here...

    }// end of if(tok.countTokens() > 0)... 

}// end of public void parseText() method

... Я залишив основне визначення класу та метод змінної ініціалізації () тощо, тому що передбачається, що якщо ви знаєте Java, ви вже знаєте, як це налаштувати. Основний клас для цього, ймовірно, повинен поширити JFrame, і у вашому загальнодоступному методі static void main () просто створити його примірник. Сподіваємось, деякі з цього коду допомагають.

ЗРЕШЕНО - Гаразд, тож, що ви будете робити далі, це створити клас "Дії" та сканувати дії (тобто "дістати світильник" або "скинути меч"). Щоб зробити це більш простим, вам доведеться мати об'єкт або метод RoomScan, щоб сканувати все видиме в обсязі і сканувати лише ті об’єкти, які виконують цю дію. Сам об’єкт обробляє обробку дій і за замовчуванням у вас повинен бути клас Item, який обробляє всі відомі дії за замовчуванням, які можна переоцінити. Тепер, якщо, наприклад, елемент, який ви хочете "отримати", міститься символом, який не належить гравцеві, відповідь за замовчуванням для отримання цього предмета у власнику має бути чимось на зразок "Не дозволить вам мати його". Тепер вам доведеться створити тонну відповідей на дії за замовчуванням на це в класі предмет або річ. Це в основному виходить з точки зору Tads3 на весь дизайн. Тому що в Tads3 кожен елемент має свою процедуру обробки дій за замовчуванням на ньому, яку аналізує аналізатор, якщо ініціалізація дії на ньому. Отже ... Я тільки кажу вам, що в Tads3 вже все це на місці, тому ДУЖЕ легко кодувати в текстовій пригоді цією мовою. Але якщо ви хочете зробити це з нуля, як у Java (вище), то я особисто впорався б із цим так само, як і був розроблений Tads3. Таким чином, ви можете змінити дії за замовчуванням, обробляючи підпрограми на самих різних об'єктах, так, наприклад, якщо ви хочете "отримати лампу", а дворецький утримує її, це може викликати відповідь у методі дій "get" за замовчуванням для Item або Об'єкт і скажуть вам, що "дворецький відмовляється здати латунну лампу". Я маю на увазі ... як тільки ти був програмістом досить довго, як у мене, то це все ДУЖЕ легкі речі. Мені старше 50 років і цим займаюся ще з 7 років. Батько був у 70-х років інструктором Hewlett Packard, тому я спочатку навчився йому від TON на комп'ютерному програмуванні. Я також зараз в армії США, як в основному, адміністратор сервера. Гм ... так, так що не здавайся. Це не так важко, як тільки ви дійсно розбиєте його на те, що ви хочете, щоб ваша програма робила. Іноді спроби та помилки є найкращим способом продовжувати подібні речі. Просто випробуй це і побачи, і ніколи не здавайся. Добре? Кодування - це мистецтво. Це можна зробити різними способами. Не дозволяйте так чи інакше здавати вас кутом у дизайні. м також в армійських резервах США як в основному адміністратор сервера зараз. Гм ... так, так що не здавайся. Це не так важко, як тільки ви дійсно розбиєте його на те, що ви хочете, щоб ваша програма робила. Іноді спроби та помилки є найкращим способом продовжувати подібні речі. Просто випробуй це і побачи, і ніколи не здавайся. Добре? Кодування - це мистецтво. Це можна зробити різними способами. Не дозволяйте так чи інакше здавати вас кутом у дизайні. м також в армійських резервах США як в основному адміністратор сервера зараз. Гм ... так, так що не здавайся. Це не так важко, як тільки ви дійсно розбиєте його на те, що ви хочете, щоб ваша програма робила. Іноді спроби та помилки є найкращим способом продовжувати подібні речі. Просто випробуй це і побачи, і ніколи не здавайся. Добре? Кодування - це мистецтво. Це можна зробити різними способами. Не дозволяйте так чи інакше здавати вас кутом у дизайні.


Це, на жаль, виключає найскладнішу частину текстового аналізатора, а саме ідентифікацію дієслова, тему та об'єкта введення користувача та відображення його на дію.
Філіпп

Щоправда, але як я це зробив, це створити клас дій та зберегти купу дій у, скажімо, класі словника, а потім перевірити на слова дії. Якщо дія включає в себе друге слово (наприклад, для дії "взяти", можливо, "взяти лампу"), тоді скануйте купу предметів (або іменника), для яких саме ці об'єкти мають сценарій для обробки дій, зроблених на них. Це все припускаючи, що ви кодуєте всю річ прямо в Java, а не намагаєтеся зробити фактичний зовнішній файл, прочитаний для складання текстових пригод.
Вільям Челоніс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.