Comment analyser la saisie utilisateur dans un jeu d'aventure texte?


16

L'analyse des commandes utilisateur dans une aventure textuelle est un spectre allant du simple «aller vers le nord» d' Aventure à quelques-unes incroyablement intelligentes dans hhgttg .

Je me souviens avoir lu de jolis modes d'emploi dans des magazines informatiques dans les années 80, mais maintenant je ne trouve presque rien sur le net, sauf une brève référence Wikipedia .

Comment feriez- vous ?


Mise à jour : je suis allé avec l'approche la plus simple possible dans mon entrée Ludum Dare .


3
Y a-t-il un problème particulier que vous essayez de résoudre?
Trevor Powell

@TrevorPowell considérant de se lancer dans une aventure faisant peu de texte pour le plaisir, et que vous voulez juste pour me familiariser de « l' état de l'art » plutôt que la plongée et la résolution de mon chemin est tout
Will

1
Utilisez Inform ; c'est la meilleure stratégie que vous puissiez utiliser. Il n'y a pratiquement aucune raison de coder manuellement une aventure textuelle de nos jours.
Nicol Bolas

@NicolBolas à moins que Ludum Dare ne s'approche? ;)
Sera le

1
Ce n'est pas aussi défaitiste que pragmatique. Entrer dans toutes les techniques d'analyse de texte avancée (au-delà des éléments évidents que n'importe qui peut trouver) est probablement hors de portée d'une seule réponse ici.
Tetrad

Réponses:


10

Avez-vous cherché dans la communauté de fiction interactive? Ils écrivent toujours des analyseurs et certains tentent de repousser les limites en mettant en œuvre de nouvelles techniques telles que le traitement du langage naturel.

Voir par exemple ce lien pour des articles décrivant les approches utilisées:

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


4
Aha, "l'aventure du texte" devient "la fiction interactive" et du coup c'est beaucoup plus googlable! Qui aurait pensé que cela changerait même de nom depuis que je l'ai joué? :) Pourtant, en regardant ces pistes, et en fait pas grand-chose s'explique malheureusement
Will

9

Le terme que vous souhaitez est «traitement du langage naturel» ou PNL. Cependant, gardez à l'esprit que les méthodes formelles sont conçues pour essayer de comprendre les textes du monde réel, alors que vous n'avez généralement besoin que de quelque chose qui fonctionne pour un sous-ensemble limité de votre langage naturel.

En règle générale, vous pouvez commencer avec une grammaire et un vocabulaire simples, puis écrire un analyseur pour cela. Une grammaire pourrait être quelque chose de simple comme ceci:

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"

Ce qui précède est une variante de la forme Backus-Naur, la manière standard de représenter les grammaires. Quoi qu'il en soit, vous pouvez utiliser un générateur d'analyseur pour générer du code pour analyser cette grammaire, ou écrire le vôtre assez facilement si votre langue a une gestion décente des chaînes. (Recherchez les «analyseurs de descente récursifs», qui utilisent une fonction pour chaque ligne de la grammaire.)

Une fois analysée, vous pouvez déterminer si la phrase est logique - «aller vers le nord» peut avoir du sens, mais «obtenir le nord vert» ne l'est pas. Vous pouvez résoudre ce problème de 2 manières; rendre la grammaire plus formelle (par exemple, avoir différents types de verbes valables uniquement avec certains types de noms) ou comparer les noms avec le verbe par la suite. La première façon peut vous aider à transmettre de meilleurs messages d'erreur au joueur, mais vous devez toujours faire la seconde dans une certaine mesure, car vous devez toujours vérifier le contexte - par exemple. "prendre la clé verte" est grammaticalement correct et syntaxiquement correct, mais vous devez toujours vérifier que la clé verte est présente.

Finalement, votre programme se retrouve avec une commande validée avec toutes les différentes parties vérifiées; alors il s'agit juste d'appeler la bonne fonction avec les arguments pour effectuer l'action.


6

L'état de l'art pour faire des aventures textuelles aujourd'hui utilise Inform 7 . La source Inform 7 se lit "comme l'anglais", de la même manière que les jeux basés sur Inform vous permettent "d'écrire en anglais". Par exemple, d'après Emily Short's Bronze :

Une chose a un texte appelé parfum. L'odeur d'une chose est généralement "rien".
La règle de l'odeur de bloc n'est répertoriée dans aucun livre de règles.
Efforcez-vous de sentir quelque chose:
    dites «Du [nom] vous sentez [l'odeur du nom]».
Au lieu de sentir une pièce:
    si une chose parfumée peut être touchée par le joueur, dites "Vous sentez [la liste des choses parfumées qui peuvent être touchées par le joueur].";
    sinon dites "L'endroit est parfaitement inodore."

L'analyseur Inform 7 est étroitement intégré à l'IDE Inform 7 et le code source complet n'est pas encore disponible pour étude:


5

Les deux meilleures sources actuelles pour apprendre à créer un analyseur d'aventure texte sont (comme cela a été mentionné) la communauté IF et la communauté de boue. Si vous recherchez les principaux forums pour ceux-ci (Intfiction.org/forum, le newsgroup rec.arts.int-fiction, Mud Connector, Mudbytes, Mudlab, Top Mud Sites), vous trouverez des réponses, mais si vous cherchez juste pour les articles, je recommanderais l'explication de Richard Bartle sur l'analyseur dans MUD II:

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

Et cette explication sur rec.arts.int-fiction:

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

Aucun manque de respect à l'égard des autres réponses, mais la création d'une grammaire CF ou l'utilisation de BNF n'est pas la solution à ce problème. Cela ne veut pas dire que cela ne pourrait pas être une solution à un problème différent, c'est-à-dire créer un analyseur de langage naturel plus avancé, mais c'est l'objet de recherches considérables et non de l'OMI dans le cadre d'une aventure de texte.


4

Au cours de ma première année à l'université, nous avons créé un jeu d'aventure à Prolog, et pour les commentaires des utilisateurs, nous avons dû utiliser une grammaire à clause définie ou DCG. Voir http://www.amzi.com/manuals/amzi/pro/ref_dcg.htm#DCGCommandLanguage pour un exemple de son utilisation comme langage de commande. Cela ressemblait à une approche fondée sur des principes (c'était uni après tout) et flexible à l'époque.


1

Vous devez définir un langage spécifique au domaine qui est toutes les phrases qui sont correctes dans votre jeu. À cette fin, vous devez définir une grammaire pour votre langue (vocabulaire et syntaxe). Le type de grammaire dont vous avez besoin est une grammaire sans contexte et il existe des outils qui génèrent automatiquement un analyseur à partir d'une description synthétique de la grammaire comme ANTLR (www.antlr.org). L'analyseur vérifie uniquement si une phrase est correcte ou non et produit un arbre de syntaxe abstraite (AST) de la phrase qui est une représentation navigable de la phrase où chaque mot a le rôle que vous avez spécifié dans la grammaire. En naviguant dans l'AST, vous devez ajouter le code qui évalue la sémantique prise par chaque mot lorsque vous jouez ce rôle par rapport aux autres mots de la phrase et vérifiez si la sémantique est correcte.

Par exemple, la phrase «La pierre mange l'homme» est syntaxiquement correcte mais pas nécessairement sémantiquement correcte (sauf si dans votre monde les pierres, peut-être les pierres magiques, peuvent manger les hommes).

Si la sémantique est également correcte, vous pouvez, par exemple, changer le monde en fonction de cela. Cela pourrait changer le contexte et donc la même phrase ne pourrait plus être sémantiquement correcte (par exemple, il ne pourrait y avoir d'homme à manger)


1

J'ai utilisé le moteur Tads3 (www.tads3.org) pour certaines des aventures textuelles que j'ai écrites. C'est plus pour les programmeurs informatiques mais c'est un langage très puissant. Si vous êtes un programmeur, Tads3 sera beaucoup plus facile à coder plus rapidement que Inform7, que j'ai également utilisé auparavant. Le problème avec Inform7 pour les programmeurs est aussi célèbre que "devinez le verbe" est pour les joueurs d'aventures de texte en ce que si vous n'écrivez pas vos phrases TRÈS soigneusement, vous allez casser le jeu. Si vous avez la patience de le faire, vous pouvez facilement écrire un analyseur en Java en utilisant la classe Tokenizer. Exemple, j'ai écrit en utilisant un JTextArea global et un tableau String [] global. Il supprime les caractères indésirables, sauf laisse AZ et 0-9 ainsi que le point d'interrogation (pour un raccourci de commande "aide"):

// 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

... J'ai laissé de côté la définition de la classe principale et la méthode initialize () de la variable, etc. car il est supposé que si vous connaissez Java, vous savez déjà comment le configurer. La classe principale pour cela devrait probablement étendre JFrame et dans votre méthode publique statique void main (), créez-en simplement une instance. Si tout va bien une partie de ce code aide.

ÉDITÉ - D'accord, alors maintenant, ce que vous feriez ensuite, c'est de créer une classe Actions et de rechercher une action (c'est-à-dire "obtenir une lampe" ou "déposer une épée"). Pour simplifier, vous devez disposer d'un objet ou d'une méthode RoomScan pour analyser tout ce qui est visible dans la portée et rechercher uniquement les objets de cette action. L'objet lui-même gère la gestion des actions et par défaut, vous devriez avoir une classe Item qui gère toutes les actions connues de manière par défaut, qui peut être remplacée. Maintenant, si par exemple, un objet que vous voulez "obtenir" est détenu par un personnage non joueur, la réponse par défaut pour obtenir cet objet détenu par son propriétaire devrait être quelque chose comme "Le ne vous laissera pas l'avoir". Vous devez maintenant créer une tonne de réponses d'action par défaut à cela dans la classe Item ou Thing. Cela vient essentiellement d'une perspective Tads3 sur la conception globale. Parce que dans Tads3, chaque élément a sa propre routine de gestion d'actions par défaut que l'analyseur appelle si une action est initialisée. Donc ... Je vous dis juste que Tads3 a déjà tout cela en place, donc c'est TRÈS facile de coder dans une aventure de texte dans cette langue. Mais si vous voulez le faire à partir de zéro, comme en Java (ci-dessus), alors je le gérerais de la même manière que Tads3 a été conçu. De cette façon, vous pouvez remplacer les actions par défaut gérant les routines sur différents objets eux-mêmes, donc par exemple si vous voulez "obtenir la lampe" et que le majordome la tient, cela pourrait déclencher une réponse dans la méthode d'action "get" par défaut pour Item ou Objet et vous dire que "Le majordome refuse de remettre la lampe en laiton." Je veux dire ... une fois que vous avez été un programmeur assez longtemps comme moi, alors tout cela est TRÈS facile. J'ai plus de 50 ans et je fais cela depuis l'âge de 7 ans. Mon père était instructeur Hewlett Packard dans les années 70, j'ai donc appris une tonne de lui au départ sur la programmation informatique. Je suis également dans les réserves de l'armée américaine en tant qu'administrateur de serveur. Hum ... ouais, alors n'abandonne pas. Ce n'est pas si difficile une fois que vous avez vraiment décomposé ce que vous voulez que votre programme fasse. Parfois, les essais et les erreurs sont la meilleure façon de procéder sur ce genre de choses. Il suffit de le tester et de voir et de ne jamais abandonner. D'accord? Le codage est un art. Cela peut se faire de différentes manières. Ne laissez pas d'une manière ou d'une autre vous bloquer dans un coin sur le design. m également dans les réserves de l'armée américaine en tant qu'administrateur de serveur maintenant. Hum ... ouais, alors n'abandonne pas. Ce n'est pas si difficile une fois que vous avez vraiment décomposé ce que vous voulez que votre programme fasse. Parfois, les essais et les erreurs sont la meilleure façon de procéder sur ce genre de choses. Il suffit de le tester et de voir et de ne jamais abandonner. D'accord? Le codage est un art. Cela peut se faire de différentes manières. Ne laissez pas d'une manière ou d'une autre vous bloquer dans un coin sur le design. m également dans les réserves de l'armée américaine en tant qu'administrateur de serveur maintenant. Hum ... ouais, alors n'abandonne pas. Ce n'est pas si difficile une fois que vous avez vraiment décomposé ce que vous voulez que votre programme fasse. Parfois, les essais et les erreurs sont la meilleure façon de procéder sur ce genre de choses. Il suffit de le tester et de voir et de ne jamais abandonner. D'accord? Le codage est un art. Cela peut se faire de différentes manières. Ne laissez pas d'une manière ou d'une autre vous bloquer dans un coin sur le design.


Cela laisse malheureusement de côté la partie la plus difficile d'un analyseur de texte, à savoir l'identification du verbe, du sujet et de l'objet de la saisie de l'utilisateur et sa mise en correspondance avec une action.
Philipp

Certes, mais comment je le ferais est de créer une classe d'actions et de stocker un tas d'actions dans, disons, une classe de dictionnaire, puis de rechercher des mots d'actions. Si l'action implique un deuxième mot (comme pour une action "prendre", peut-être "prendre une lampe"), faites analyser un groupe d'objets (ou de noms) où ces objets eux-mêmes auraient un script pour gérer les actions effectuées sur eux. Tout cela suppose que vous codiez l'intégralité de la chose en Java et que vous n'essayiez pas de lire un fichier externe réel pour compiler des aventures de texte.
William Chelonis
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.