Inform 6 - Exact expression of name when call it from parser

Hi!

I encounter a trouble with Inform 6 today.

It’s about an expression in french.
I try to done a matchbox with matches in it.
match is “allumette”, matches->“allumettes”, box->boite, matchbox->“boite d’allumettes”->box of matches.
The trouble is when I call “allumette”(match in singular) from parser it recognize it as the matchbox not the match insind the box.

The code:

Object boiteAllu "boite d'allumettes" piece
    with description "Une petite boite d'allumettes.",
    name 'boite', 'allumettes'
    has openable,
    has container,
    has female;

Object allumette "allumette" boiteAllu
    with description "Une allumette en bois",
    name 'allumette',
    has female;

If you are compiling to z5, dictionary words are truncated after the first 9 letters. In your case, ‘allumette’ and ‘allumettes’ are both being saved in the dictionary as ‘allumette’, so they both appear to be the same word to the parser.

To work around this, I think you need to write a parse_name routine where you manually check the word length if the dictionary word is ‘allumette’.

3 Likes

Hi,

Thanks for your reply.

I have done a parse_name section for match the words but don’t know how I can check manually the word length.

I have this in my code for now:

Object boiteAllu "boite d'allumettes" piece
    with description "Une petite boite d'allumettes.",
    parse_name
    [w;
    if (NextWord() == 'boite' && NextWord() == 'd^'){
        w=NextWord();
        if(w=='allumette'){
            print WordLength(w);
            return 3;
        }
    }
    return 0;
    ],
    has openable,
    has container,
    has female;

Someone give me the WordLength() function but in my code it return the number 3 so I don’t really understand why WordLength() return me this number. Can you guide me about how to check the 10nd letter of allumette? So this must be or not a ‘s’.

I was just about to respond when I noticed a problem in your original example. d'allumettes is one word, not two, and you had a stray comma in the definition of name. If you fix those problems, as shown below, you don’t need the parse_name routine.

Object boiteAllu "boite d'allumettes" piece
with
  name 'boite' 'd^allumettes',
  description "Une petite boite d'allumettes.",
has container female openable;

Object allumette "allumette" boiteAllu
with
  name 'allumette',
  description "Une allumette en bois.",
has female;

If you still need to use a parse_name routine to check long words in another situation, the things you need are described in chapter 28 of the DM4. The current word number is stored in the global variable wn. Every time you read the next word using NextWord(), wn is incremented. WordLength(wn) tells you how many characters are in the word that you just read and WordAddress(wn) returns a byte array of the characters in that word so that you can check the individual characters if needed.

1 Like

The WordLength() routine takes as input the “word” number in the player’s command and returns the number of characters in what the player typed that were matched to that “word”. What counts as a “word” may be different from what you expect because certain things in player input (like commas) are treated as their own word. For example, the command >BOB, JUMP has three “words”: 1 = “bob”, 2 = (comma), 3 = “jump”.

A .parse_name() routine that signals a match is supposed to return the number of “words” that were matched. You are executing print WordLength(w) but still have return 3, so 3 is what is returned by the routine.

As Warrigal notes, there is a routine WordAddress() that should be in your library (but can be found in StdLib 6/11 or on the forum if needed). That routine returns the memory address of the start of the “word” corresponding to the number given as a parameter. You can then use that address as the basis of a (zero-indexed) character array (->) to look at the nth character. Something along the lines of this should work as you seem to intend:

Object boiteAllu "boite d'allumettes" piece
	with description "Une petite boite d'allumettes.",
	name 'petite' 'boite',
	parse_name
	    [c w swn;
	            swn = wn;       ! save parser's current word number pointer
	            if (NextWord() == 'boite' && NextWord() == 'd^') {
	                    c=(WordAddress(wn))->9; ! ->0 is 1st character of word, ->9 is 10th
	                    w=NextWord();
	                    if(w=='allumette' && c == 's') return 3;
	            }
	            wn = swn;       ! return current word number pointer to saved place
	            return -1;      ! signal that .name property should be tried next
	    ],
	has openable,
	has container,
	has female;

The above code assumes that your library will be splitting “d’allumettes” into “d’ allumetes” before tokenizing, which I believe is done in the French libraries. The object will match “petite”, “boite”, or “boite d’allumettes” but NOT “petite boite d’allumettes” – to allow more flexible parsing, you might want something like:

Object boiteAllu "boite d'allumettes" Start
	with description "Une petite boite d'allumettes.",
	name 'petite' 'boite' 'd^' 'allumettes',    ! 'allumettes' is same as 'allumette'
	parse_name
	    [chr wd score;
	            while(true) {
	                    chr=(WordAddress(wn))->9; ! ->0 is 1st character of word, ->9 is 10th
	                    wd=NextWord();
	                    if (WordInProperty(wd, self, name)) {
	                            if (wd == 'allumette' && chr ~= 's') return 0;
	                            else score++;
	                    } else return score;
	            }
	    ],
	has openable,
	has container,
	has female;

For some useful patterns of .parse_name() routines see zarf’s tips and tricks at Inform: Parse_Name Variations.

2 Likes

Ho thanks a lot for your work this code solve the trouble of plural on the word “allumettes”.
I will learn this code cause I don’t understand all the functions (.TryNormalParsing; line as example);
But yeah it work :slight_smile:
Thanks you again for explanations.

The .TryNormalParsing; statement is a label – a target for a jump statement that was in an earlier version – which I forgot to remove when restructuring the routine. The portions of the routine involving swn were also superfluous in this version, and it wasn’t necessary to return -1 in this particular case since all of the words in the .name property are already being checked.

Sorry about those oversights; I’ve edited the answer to remove them.

1 Like