Defining and using 'Read' verb in I6 + Puny. Why does Examine override it?

Inform 6 + Puny. I’m trying to define a new verb for reading. However, when trying to ‘read’ something, the game ‘describes’ it instead.

[ ReadSub;
    if (noun == 0) "Read what?";
    print "[ You have no interest in trying to read that. ]";

    rtrue;
];

Verb 'read'
    * noun -> Read;

[ FooSub;
    if (noun == 0) "Read what?";
    print "[ You have no interest in trying to read that. ]";

    rtrue;
];

Verb 'foo'
    * noun -> Foo;

!...

Object -> Sign "sign"
	with
		name "sign",
		before [;
			Read:
				"Go away!";
			Foo:
				"Foo";
		];

Here “foo-ing” works but reading doesn’t.

> x sign
There is nothing special about the sign.
 
> read sign
There is nothing special about the sign.
 
> foo sign
Foo

How do I define read whilst leaving examine alone?

chapter 30 in the inform DM4:

Extend 'read' replace
    *  noun -> Read;

[ ReadSub; 
    "There's nothing legible on ",(the)noun,".";
]; 
1 Like

In other words, it’s because there’s already a grammar line for the verb “read” that maps to examining. You need to use replace to replace that line instead of just adding another one.

2 Likes

You should read all warnings that the compiler produces. In this case, for a PunyInform project, you get something like:
mygame.inf(117): Warning: This verb definition refers to “read”, which has already been defined. Use “Extend last” instead.

2 Likes

To be fair, if you saw that warning and changed the Verb declaration to Extend last, it would not solve your problem. :)

Extend last has the same behavior – the originally-defined Examine verb takes precedence. You want Extend replace, as improvmonster said.

1 Like

Whenever you change the grammar for an existing verb, you should first check to see how it is defined in grammar.h. In the case of read, the grammar definition is:

Verb 'read'
* noun -> Examine
* 'about' topic 'in' noun -> Consult reverse
* topic 'in' noun -> Consult reverse;

This means you have two options. You can either extend the grammar to insert a new line at the start or you can replace it completely. Here’s how:

Extend 'read' first
* noun -> Read;

OR

Extend 'read' replace
* noun -> Read
* 'about' topic 'in' noun -> Consult reverse
* topic 'in' noun -> Consult reverse;

The first method will leave two definitions for 'read' noun, but the second one will never be reached. The second method replaces everything.

In your ReadSub, you don’t have to test for noun == 0, as you don’t have a grammar definition for 'read' by itself. If you did, that would be different.

In your print statement, you need to delete the square brackets and add a newline. Better still, delete the print keyword and rtrue, as the bare quoted string will print a newline and return true.

Also, your print statement does not take account of plural objects.

Here’s a suggested replacement:

[ ReadSub;
if (ObjectIsUntouchable(noun))
rtrue;
"There’s nothing legible on ", (ThatOrThose)noun, ".";
];

You don’t need to change the grammar. Just check if the verb typed by the player is actually read:

Object -> Sign "sign"
	with
		name 'sign',
		before [;
            Examine:
                if (verb_word == 'read')
                    "Go away!";
        ];

> x sign
There is nothing special about the sign.

> read sign
Go away!

1 Like

You put double quotation marks around the property name: "sign". Put single quotation marks around 'sign'. Although both work, it is a dictionary word and not a string of characters.

Object -> Sign "sign"
	with
		name 'sign',
		before [;
            Examine:
                if (verb_word == 'read')
                    "Go away!";
                "You should READ what it said instead.";
        ];

> x sign
You should read what it said instead.

> read it
Go away!