AddInfo()
FUNKTION:
     varargs void AddInfo( frage, meldung
			   [, indent [, [silent [, casebased] ] ] );

DEFINIERT IN:
     /std/npc/info.c

ARGUMENTE:
     string/string* frage
	Schluesseltext(e) auf die Informationen gegeben werden sollen.
     string/closure meldung
	Information, die gegeben werden soll/Closure
     string indent
	Text, der sich bei mehrzeiligen Meldungen wiederholen soll.
     int/string silent
	Ist silent gesetzt, so erfolgt Antwort nur an Fragenden.
     string/closure casebased
	Closure mit Returnwert string oder int.

BESCHREIBUNG:
     Wenn ein Spieler ein NPC mittels "frage <monstername> nach <frage>" nach
     einer Information mit dem Schluessel 'frage' fragt, so wird die
     entsprechende 'meldung' ausgegeben (oder die Closure in 'meldung'
     gerufen und der zurueckgegebene Text ausgegeben). Der Meldung wird
     der Name des Monsters vorangestellt.

     Frage:
      Schluessel muessen kleingeschrieben sein, koennen aber Leerzeichen
      enthalten.

     Meldung:
      Wenn kein 'indent' angegeben ist, muss man die Meldung selbst
      umbrechen.

     Indent:
      Wird ein 'indent' angegeben so wird jeder Zeile hinter dem
      Monsternamen noch das 'indent' vorangesetzt. Zusaetzlich wird
      'meldung' auf jeden Fall sauber umgebrochen.
      Ein typisches indent ist "sagt: ".

     Silent:
      Bei 'silent'==1 erfolgt keine Textausgabe der Antwortmeldung im Raum,
      ist 'silent' ein String, so wird jener an alle anderen Spieler ausser
      dem Fragesteller im Raum ausgegeben.

     Casebased:
      Die als Closure angegebene Methode entscheidet, ob oder wie der NPC 
      auf diese Frage antworten soll:
      - return 0:	normale Antwort mit "meldung"
      - return 1:	keine Antwort/Antwort mit DEFAULT_NOINFO
      - return string:	Antwort mit string unter Beruecksichtigung eines
			indent

     Die Strings von 'silent' und 'meldung' werden geparsed. Dabei werden die
     Schluesselworte @WER, @WESSEN, @WEM, @WEN durch TP->Name(..) ersetzt und
     @CAP_WER, @CAP_WESSEN, @CAP_WEM, @CAP_WEN durch capitalize(TP-Name(..)).

     Mittels der in <npc.h> definierten Frage DEFAULT_INFO kann eine
     Meldung gesetzt werden, die gegeben werden soll, wenn der Spieler
     etwas fragt, auf das keine Antwort vorgegeben ist (das loest
     SetProp(P_DEFAULT_INFO, <text>) ab).

BEISPIELE:
     ### eine Standardantwort setzen ###
     AddInfo(DEFAULT_INFO, "starrt Dir boese in die Augen.\n");
     // identisch zu
     SetProp(P_DEFAULT_INFO, "starrt Dir boese in die Augen.\n");

     ### einfache Beispiele, auch mit casebased ###
     AddInfo(({"knete","kohle"}),
	     "sagt: ich habe so etwas nicht.\n");
     AddInfo("geld",
	     "Ich habe zwar kein Geld, aber ... blablabla ...",
	     "sagt: " );
     AddInfo("muenzen",
	     "fluestert: Du willst Geld?\n",
	     0,
	     "fluestert @WEM etwas zu.\n");

     // "frage monster nach geld": alle im Raum hoeren
     //  Das Monster sagt: Ich habe zwar kein Geld, aber ...
     //  Das Monster sagt: ... blablabla ...

     // "frage monster nach muenzen":
     // - der Fragensteller hoert:
     //   "Das Monster fluestert: Du willst Geld?"
     // - alle andere hoeren:
     //   "Das Monster fluestert <Fragenstellernamen> etwas zu."

     ### dynamisch ###
     // ein Prototyp, damit wir die Methode bekannt machen
     static string query_kekse();
     ...
     AddInfo(({"keks","kekse"}),
	     #'query_kekse,		// ein Verweis auf die Funktion
	     "sagt: ");
     ...
     static string query_kekse() {
      if(present("keks"))
       return("Ich hab noch welche. Aetsch!");
      return("Menno. Keine mehr da!");
     }

     // "frage monster nach keks":
     // - wenn es noch Kekse hat, hoeren alle:
     //   "Das Monster sagt: Ich hab noch welche. Aetsch!
     // - sonst:
     //   "Das Monster sagt: "Menno. Keine mehr da!

     ### dynamischer ###
     // ein Prototyp, damit wir die Methode bekannt machen
     static string query_kekse();
     static mixed case_fighting();
     ...
     AddInfo(({"keks","kekse"}),
	     #'query_kekse,"		// ein Verweis auf die Funktion
	     sagt: ",
	     0,				// nicht silent :)
	     #'case_fighting);		// noch ein Funktionsverweis
     ...
     static string query_kekse() {
      if(present("keks"))
       return("Ich hab noch welche. Aetsch!");
      return("Menno. Keine mehr da!");
     }

     static mixed case_fighting() {
      if(InFight())
       return("Keine Zeit fuer Kekse. Muss kaempfen.");
      return 0;
     }

     // "frage monster nach keks":
     // - wenn es kaempft, hoeren alle:
     //   "Das Monster sagt: Keine Zeit fuer Kekse. Muss kaempfen.
     // - sonst, wenn es noch Kekse hat, hoeren alle:
     //   "Das Monster sagt: Ich hab noch welche. Aetsch!
     // - sonst:
     //   "Das Monster sagt: "Menno. Keine mehr da!


     ### dynamisch und komplex ###
     // ein Prototyp, damit wir die Methode bekannt machen
     static string question_gold();
     ...

     // "gold" wird eine Closure auf die Methode question_gold()
     // zugewiesen, ausserdem soll es still bleiben (wir informieren
     // den Restraum selbst)
     AddInfo("gold",#'question_gold,"murmelt: ",1);
     ...

     // los gehts, wir generieren unsere Antwort selbst
     static string question_gold() {
      int money;
      string *y, objstr;
      object o;
      // wieviel Kohle hat der Spieler
      money=this_player()->QueryMoney();
      y=allocate(0);
      // und jetzt suchen wir die Dinge aus Gold
      o=first_inventory(this_player());
      while(o) {
       if(o->QueryMaterial(MAT_GOLD)>0 &&
          strstr(object_name(o),"/obj/money"))
        y+=({o->name(WER,1)});
       o=next_inventory(o);
      }

      // das geht an alle anderen im Raum, silent bietet sich hier
      // nicht an, weil es mehrere Moeglichkeiten gibt
      say(break_string(
       Name(WER,1)+" murmelt "+
       this_player()->name(WEM,1)+
       " etwas zu"+
       ((money || sizeof(y))?
        " und glotzt "+
        this_player()->QueryPronoun(WEN)+" gierig an.":
        "."),78),({this_player()}));

      // und hier die Antwort an den Spieler selbst, mit vielen
      // Verzweigungen fuer dessen Besitztum
      return("Ich hab kein Gold bei mir."+
          ((money || sizeof(y))?
           " Aber du "+
           (money?"hast ja jede Menge Kohle bei dir, so etwa "+money+
            " Muenzen."+
            (sizeof(y)?
             " Ausserdem "+
             ((sizeof(y)==1)?"ist":"sind")+
             " auch noch "+CountUp(y)+" aus Gold.":
             ""):
            (sizeof(y)?" Aber was du so bei dir hast: "+
             CountUp(y)+
             (sizeof(y)==1?" ist":" sind")+
             " aus Gold.":"")):
           ""));
     }

     // "frage monster nach gold"
     // - der Fragesteller hoert zB:
     //   Das Monster murmelt: Ich hab kein Gold bei mir. Aber du hast ja
     //   Das Monster murmelt: jede Menge Kohle bei dir, so etwas <number>
     //   Das Monster murmelt: Muenzen. Ausserdem ist/sind noch <object1>
     //   Das Monster murmelt: und <object2> aus Gold."
     // - die Umstehenden hoeren:
     //   "Das Monster murmelt @WEM etwas zu."
     //   oder
     //   "Das Monster murmelt @WEM etwas zu und glotzt ihn/sie gierig an."

SIEHE AUCH:
     Verwandt:  AddSpecialInfo(L), RemoveInfo(L)
     Props:     P_PRE_INFO, P_DEFAULT_INFO
     Files:     /std/npc/info.c
     Loggen:    P_LOG_INFO
     Interna:   GetInfoArr, do_frage

7.Apr 2004 Gloinson
