Forum moved to if-forum.org
Autor Nachricht
<  [Glulx] Fehler in der ProcessGermanVerbs()
Kris
BeitragVerfasst am: Mo, 14 Feb 2005 - 9:59  Antworten mit Zitat
Kompassleser
Kompassleser


Anmeldungsdatum: 21.02.2004
Beiträge: 198
Wohnort: Rheinmain

Hallo,

ich bin da auf einen Bug in der Routine ProcessGermanVerbs gestoßen. (Email an Max ist unterwegs)
Gibt man ein Verb ein, dass mit einem "e" beginnt, wird dieses auch abgeschnitten und so in den buffer für den Befehl "again" abgelegt.
Gibt man "g" ein, erkennt der Parser das Verb nicht mehr.

Da in meinem Spiel unbekannte Wörter und Verben ausgegeben werden, kam eben die Meldung, "Ich kenne das Verb "rzähl" nicht" (anstatt erzähl).

Unter Z-Code läuft es (das nur zur Info)

hier der Code von Zeile 363 bis 375 aus german.h:


Code:
...
#ifnot; ! TARGET_GLULX
verbend = parse-->2 + parse-->3 - 1;
for (x = 0: x < (parse-->0 - 1): x++) {
  if (buffer->(parse-->(x*3+3)) == ',') {
       verbend = parse-->((x+1)*3+2) + parse-->((x+1)*3+3) - 1;
       if (buffer->verbend == 'e') buffer->verbend = ' ';
       flag = 1;
  };
};     
if ((buffer->verbend == 'e') && (parse-->3 > 2) && (flag ~= 1)) buffer->verbend = ' ';
#endif; ! TARGET_

];


Das Problem tritt nur auf, wenn es sich um keine Order handelt, das Verb also am Anfang steht. Aus diesem Grund habe ich den Fehler nach der ForNext-Schleife gesucht.

Was ich nicht verstehe (gut, da ist noch einiges mehr :) ist, das verbend nach dem Eingeben immer die Verblänge + 3 hat, nach dem lesen aus dem again-buffer aber die korrekte Länge ausweist.

Da der Fehler ja nur Auftritt, wenn das Verb am Anfang steht, habe ich als workaround in der Zeile 372 noch die Bedingung (x > 0), also Wort nicht an erster Stelle, eingefügt:

Code:
if ((x > 0) && (buffer->verbend == 'e') && (parse-->3 > 2) && (flag ~= 1)) buffer->verbend = ' ';


Es funktioniert, ist aber sicher nicht *die Lösung*.

Wer also zur Zeit an einem Glulx-Spiel für den GP sitzt und die Korrektur bis dahin nicht veröffentlicht wurde, kann es damit versuchen (ich übernehme keine Gewähr ;-)

Gruß Kris
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Martin
BeitragVerfasst am: Mo, 14 Feb 2005 - 11:53  Antworten mit Zitat
Experte
Experte


Anmeldungsdatum: 25.08.2002
Beiträge: 677
Wohnort: München

Kris hat folgendes geschrieben:
Da der Fehler ja nur Auftritt, wenn das Verb am Anfang steht, habe ich als workaround in der Zeile 372 noch die Bedingung (x > 0), also Wort nicht an erster Stelle, eingefügt:

Und das löst das Problem? Die Zählerveriable x sollte eigentlich immer größer als Null sein, weil sie einfach den Wert hat, auf dem sie nach Durchlaufen der Schleiße stehen geblieben ist. Die Bedingung, dass es sich um das erste Wort handelt, steht in flag: Ist sie Null, war's das erste Wort, denn wenn es ein Wort nach einem Komma war, wird flag auf eins gesetzt. Etwas kompliziert, finde ich.

Der Fehler liegt hier woanders: Nachdem du 'g' eingegeben hast, wird die alte Eingabe, buffer3, zurück in den buffer kopiert. Dann wird die Routine LanguageToInformese aufgerufen, allerdings bevor der neu eingelesene Buffer in Tokens zerlegt wird.

parserm.h, Zeile 1183 ff.
Code:

  .ReParse;

    parser_inflection = name;

!  Initially assume the command is aimed at the player, and the verb
!  is the first word

#ifdef TARGET_ZCODE;
    num_words=parse->1;
#ifnot; ! TARGET_GLULX
    num_words=parse-->0;
#endif; ! TARGET_
    wn=1;
#ifdef LanguageToInformese;
    LanguageToInformese();
#ifv5;
!   Re-tokenise:
    Tokenise__(buffer,parse);
#endif;
#endif;


Das heißt also, im Buffer steht 'erzähle dem mann was vom pferd', im Feld parse, in dem die Wörter abgelegt werden, steht immer noch 1, 'g//', 1, 5. Dummerweise greift LTI aber auf parse zu, und liest den falschen Input. verbend ist 5, und dort steht das 'e' von 'erzähle'. Wenn du 'again' oder 'nochmal' sagst, solltest du den Fehler nicht mehr sehen.

Warum läuft es aber korrekt im z-Code? Tja, um 'e', 'se', 'ne' als englische Synonyme für die östlichen Himmelsrichtungen zuzulassen, gibt es dort die Abfrage, dass das Wort länger als 2 Buchstaben lang sein muss. Diese Abfrage gibt es im Glulx-Code auch:

Code:
(parse-->3 > 2)


Nur ist sie nicht richtig: Es wird geprüft, ob das erste Wort hinter der zweiten Stelle anfängt, und das tut es bei Glulx immer. Hier müsste

Code:
(parse-->2 > 2)


stehen, vgl., man kann's offensichtlich gar nicht oft genug posten, Roger Firths Inform FAQ.

Deshalb mein Vorschlag: Probiere einmal, den Input vor und nach der Analyse zu "tokenisieren":

parserm.h, Zeilen 1265 ff
Code:

!  Now try for "again" or "g", which are special cases:
!  don't allow "again" if nothing has previously been typed;
!  simply copy the previous text across

    if (verb_word==AGAIN2__WD or AGAIN3__WD) verb_word=AGAIN1__WD;
    if (verb_word==AGAIN1__WD)
    {   if (actor~=player)
        {   L__M(##Miscellany,20); jump ReType; }
#ifdef TARGET_ZCODE;
        if (buffer3->1==0)
        {   L__M(##Miscellany,21); jump ReType; }
#ifnot; ! TARGET_GLULX
        if (buffer3-->0==0)
        {   L__M(##Miscellany,21); jump ReType; }
#endif; ! TARGET_
        for (i=0:i<INPUT_BUFFER_LEN:i++) buffer->i=buffer3->i;
       
        ! Neu: Wiederengelesenen Input in Tokens zerlegen:
        Tokenise__(buffer,parse);
         
        jump ReParse;
    }


Der von dir zitierte Code hat übrigens noch einen Fehler: Anstatt zu prüfen, ob ein Wort ein Komma ist, wird geprüft, ob der Startpunkt im Buffer 44 ist, wieder eine Verschiebung der Indizes. Zudem würde hier eine Vokabel als ZSCII-Zeichen abgefragt. Richtig müsste es (vermutlich) heißen:
Code:

for (x = 0: x < (parse-->0 - 1): x++) {
  if (buffer->(parse-->(x*3+1)) == ',//') {
       verbend = parse-->((x+1)*3+2) + parse-->((x+1)*3+3) - 1;
       if (buffer->verbend == 'e') buffer->verbend = ' ';
       flag = 1;
  };
};


Probiere dies bitte mal aus, es ist nicht getestet.

Der Fehler tritt übrigens auch in der z-Version auf, wenn man nämlich ein Verb benutzt, dessen fünfter Buchstabe 'e' ist und 'again' sagt, oder bei einem 'e' an siebter Stelle und 'nochmal', vgl. diese Passage aus Wilhelm Tell:

Code:

>i
Du trägst:
  einen Köcher (angezogen)
    drei Pfeile
  einen Bogen

>entferne bogen
Du hast diesen schon.

>again
Dieses Verb verstehe ich nicht.

>reibe bogen
Damit erreichst du nichts.

>again
Damit erreichst du nichts.

_________________
Every silver lining has a cloud.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Kris
BeitragVerfasst am: Mo, 14 Feb 2005 - 13:36  Antworten mit Zitat
Kompassleser
Kompassleser


Anmeldungsdatum: 21.02.2004
Beiträge: 198
Wohnort: Rheinmain

Vielen Dank für den ausführlichen Bericht,

konnte natürlich nicht alles in der Mittagspause umsetzen :-)

Martin hat folgendes geschrieben:
Und das löst das Problem? Die Zählerveriable x sollte eigentlich immer größer als Null sein, weil sie einfach den Wert hat, auf dem sie nach Durchlaufen der Schleiße stehen geblieben ist.


x entspricht beim ersten Parsen der Anzahl der "Wörter", beim "again" aber ist es 0 (da parse-->0-1 ebenfalls 0 ist).

Ich werde heute abend gerne Deinen Code testen und melde mich dann wieder.

Dank und Gruß


Kris
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Kris
BeitragVerfasst am: Di, 15 Feb 2005 - 9:52  Antworten mit Zitat
Kompassleser
Kompassleser


Anmeldungsdatum: 21.02.2004
Beiträge: 198
Wohnort: Rheinmain

Also, ich habe das gestern Abend mal getestet:

Martin hat folgendes geschrieben:
Nur ist sie nicht richtig: Es wird geprüft, ob das erste Wort hinter der zweiten Stelle anfängt, und das tut es bei Glulx immer. Hier müsste

Code:
Code:
(parse-->2 > 2)
 



stehen, vgl., man kann's offensichtlich gar nicht oft genug posten, Roger Firths Inform FAQ.


Also das, was ich alles ausprobiert habe, funktioniert mit der Änderung.
Witzig, und ich habe mich immer geärgert, dass man bei Glulx "e" nicht für Osten eingeben kann, bei Z-Code aber schon :-)
(habe es aber nicht weiterfverfolgt)



Martin hat folgendes geschrieben:
Der von dir zitierte Code hat übrigens noch einen Fehler: Anstatt zu prüfen, ob ein Wort ein Komma ist, wird geprüft, ob der Startpunkt im Buffer 44 ist, wieder eine Verschiebung der Indizes. Zudem würde hier eine Vokabel als ZSCII-Zeichen abgefragt. Richtig müsste es (vermutlich) heißen:


Code:
for (x = 0: x < (parse-->0 - 1): x++) {
  if (buffer->(parse-->(x*3+1)) == ',//') {
      verbend = parse-->((x+1)*3+2) + parse-->((x+1)*3+3) - 1;
       if (buffer->verbend == 'e') buffer->verbend = ' ';
       flag = 1;
  };
};



Ich habe beide Variationen einmal versucht, und eine print-Anweisung als Kontrolle eingefügt.

Wenn ich bei ',' ">mann, spring" eingebe, trifft es zu,
bei ',//' trifft diese Bedingung bei gleicher Eingabe nicht zu.


Martin hat folgendes geschrieben:
Der Fehler tritt übrigens auch in der z-Version auf, wenn man nämlich ein Verb benutzt, dessen fünfter Buchstabe 'e' ist und 'again' sagt, oder bei einem 'e' an siebter Stelle und 'nochmal', vgl. diese Passage aus Wilhelm Tell:


... auch das ist mit Deiner Korrektur behoben :-)


Martin: Schickst Du die Mail an Max?



Vielen Dank nochmal!


Grüße


Kris
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Martin
BeitragVerfasst am: Di, 15 Feb 2005 - 14:19  Antworten mit Zitat
Experte
Experte


Anmeldungsdatum: 25.08.2002
Beiträge: 677
Wohnort: München

Zitat:
Wenn ich bei ',' ">mann, spring" eingebe, trifft es zu, bei ',//' trifft diese Bedingung bei gleicher Eingabe nicht zu.

Okay, da war ich etwas zu schnell, ich hatte das buffer übersehen. Der Code ist richtig, wie er ist: Es wird geprüft, ob am Wortanfang das Zeichen ',' steht. Und da das ein delimiter ist, ist damit das ganze Wort bestätigt.

Ich wollte wohl folgendes sagen:
Code:

if (parse-->(x*3+1) == ',//') { ... }

Entschuldigung.

Kris hat folgendes geschrieben:
Martin: Schickst Du die Mail an Max?

Ja, mache ich.
_________________
Every silver lining has a cloud.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Alle Zeiten sind GMT + 1 Stunde (MEZ)

Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Seite 1 von 1
if-de :: Forum Foren-Übersicht  >  Inform & Glulx

Neues Thema eröffnen   Neue Antwort erstellen


 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.



Kontakt: Administrator

Powered by phpBB and NoseBleed v1.05