IF-Forum

» IF-Forum - Autorencafé - Schreiben! - [Glulx] Fehler in der ProcessGermanVerbs()
AntwortenNeues ThemaNeue Umfrage

[Glulx] Fehler in der ProcessGermanVerbs()

Geschrieben um 10:59 am 14.02.2005 | Zitat | Editieren | Löschen
Kris
Mitglied
Dr Gumby
Beiträge: 181

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:



#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:

```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
Geschrieben um 12:53 am 14.02.2005 | Zitat | Editieren | Löschen
Martin
Avatar
Mitglied
Prof Gumby
Beiträge: 634

Kris:

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.


  .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:

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

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


!  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:


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:


>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.
Geschrieben um 14:36 am 14.02.2005 | Zitat | Editieren | Löschen
Kris
Mitglied
Dr Gumby
Beiträge: 181

Vielen Dank für den ausführlichen Bericht,

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

Martin:

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

Geschrieben um 10:52 am 15.02.2005 | Zitat | Editieren | Löschen
Kris
Mitglied
Dr Gumby
Beiträge: 181

Also, ich habe das gestern Abend mal getestet:

Martin:

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



(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:**
> 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:

```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:**
> 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
Geschrieben um 15:19 am 15.02.2005 | Zitat | Editieren | Löschen
Martin
Avatar
Mitglied
Prof Gumby
Beiträge: 634

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:


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

Entschuldigung.

Kris:

Martin: Schickst Du die Mail an Max?

Ja, mache ich.

AntwortenNeues ThemaNeue Umfrage
Powered by Spam Board SVN © 2007 - 2021
Impressum / Datenschutz