Help wanted writing I6 library tests

Nope, that’s a new bug. See, we’re already making progress…

Filed inform7.com/mantis/view.php?id=1890 .

Yep. In light of the interpreter hang, I’m thinking that we should update dotest.py to add a timeout arg to the select call in accept_output(). Let me know if you want me to put together a patch for this. For now, I’ve commented out the “dan, x” commands in my ex32.inf to avoid hanging the entire test script.

Ideally we’d be testing both zcode and glulx.

Agree. Seems like we could link the glk port of frotz against remglk and be good to go.

Is that the one in the garglk source tree? Gargoyle defaults to bocfel now, so I’d assume there are advantages to using it instead.

Also, are binaries for gluxer available anywhere? Or could anyone compile it on debian/ubuntu for me? My C skills are sadly still basically nonexistent.

You’re probably right. I did a search for “glk zcode interpreter” and found a reference to the glk version of frotz on this Gargoyle page.

Try this:

mkdir ifstuff
cd ifstuff
git clone https://github.com/erkyrath/glulxe
git clone https://github.com/erkyrath/remglk
cd remglk
make
cd ../glulxe
Open Makefile in the text editor of your choice.
You'll see five triplets of variables at the top, four of which are commented out with # marks. These tell glulxe which glk library to use.
Comment out the cheapglk ones and uncomment the remglk ones. They look like this:
    GLKINCLUDEDIR = ../remglk
    GLKLIBDIR = ../remglk
    GLKMAKEFILE = Make.remglk
Save the file and exit your text editor.
make
mv glulxe glulxer

Go for it.

I’ve moved ex23.inf to the bugs directory, since it’s a bug.

As for the idea of Zcode testing… yeah, I suppose so. I have fizmo compiled with remglk lying around.

I pulled down your -Z changes, built fizmo+remglk, and ran zcode tests successfully. Very nice.

I contacted Christoph Ender, the author of fizmo, and provided some feedback on building fizmo+remglk.

In response, he decided to streamline the process and has released a new beta version of fizmo with explicit remglk support.

So, thanks to Christoph, it’s now easier to set up automated zcode testing with fizmo.

Here are some brief instructions, assuming that remglk is already installed:

git clone https://github.com/chrender/fizmo-dist.git
cd fizmo-dist
git submodule init
git submodule update
autoreconf -fi
./configure --enable-remglk --with-remglk-includedir=/full/path/to/remglk/headers --with-remglk-libdir=/full/path/to/remglk/lib
(If configure gives you an error msg about sdl2 not being installed, install it or rerun the configure command with --disable-sdl added.)
make
(The compiled fizmo+remglk will be in fizmo-remglk/src/fizmo-remglk/fizmo-remglk. For convenience you can:)
ln -s fizmo-remglk/src/fizmo-remglk/fizmo-remglk fizmor

It looks like Zarf fixed two-thirds of the manifested problem. The remaining third appears to have something to do with fallout from inform7.com/mantis/view.php?id=1885). I had a nasty time trying to figure out just what Roger Firth was doing and thinking at that point in the old 6.40 repo. For the time being, I’ve rolled back that portion of parserm.h to before when I tried to consolidate all that code into InformLibrary.actor_act(). Evidently I didn’t completely understand it and so this bug was compounded.

I’m in some serious need of help. The ex23.inf bug is fixed, but in the process of fixing it, github.com/DavidGriffith/inform6lib/issues/30 showed up again. Could I please get a few more sets of eyes looking at this problem?

I grabbed the latest inform6lib from git. This is what I’m seeing with the test program for issue 30:

If I add an objectloop to Initialise that moves all rocks to the girl, then I get this, which mirrors the first output:

So:

  • A non-action (taking a rock she already has, or dropping a rock that’s already on the ground) applied to a single rock produces good output.
  • A non-action applied to a group of rocks produces “There is no reply.” (seems wrong).
  • A significant action (taking a rock she doesn’t have, or dropping a rock she does have) applied to a single rock produces good output, and the model world changes accordingly.
  • A significant action applied to a group of rocks produces a bunch of operations on nothing, and the model world does not change.

Somehow your test inspired me to look again and I found something: I managed to leave out a tidbit from the semi-rollback and I now realize that testing or not testing inp1 determines which bug manifests. It’s hopefully down to a simple test now!

This fixes #30 and breaks #34

if (actor ~= player && inp1) {

This fixes #34 and breaks #30

if (actor ~= player) {

The problem is not yet solved, but I think I can go to sleep now without having nightmares of code flying around in my head.

I’m tried this for the if, and it seems to fix both #30 and #34. It’s now in the latest git repo. Please beat on it and see if I managed to break something else in the process.

if ((actor ~= player && inp1 ~= nothing) || (actor ~= player && (inp1 == nothing && metaclass(inputobjs-->1) == nothing)) ) {

“girl, jump” is behaving strangely (expect her to wave once). Also, “girl, drop rocks” -> “There is no reply.” (instead of “They’re already here.”).

Oh geez… I seem to have completely forgotten to test GIRL, DROP ROCKS. This hasn’t worked at all in the time I’ve had #30 to deal with. The problems with GIRL, JUMP seem to be quelled, strangely, by this:

grammar [; if (verb_word == 'jump') { action = ##WaveHands; noun = Stone; ! second = 0; rtrue; } ! Didn't understand any of this, bailing out. ],

Notice that I had noun set to Stone.

At the critical if statement:

GIRL, DROP ROCKS (when rocks are indeed held)
inp1 == nothing
inp2 == nothing
inputobjs–>1 == Class
inputobjs–>2 == nothing
inputobjs–>3 == nothing
noun == nothing
actor == girl

GIRL, DROP ROCKS (when no rocks are held)
inp1 == Class
inp2 == girl
inputobjs–>1 == Object
inputobjs–>2 == Class
inputobjs–>3 == girl
noun == <routine 8235>
actor == girl

girl, jump
inp1: nothing
inp2: nothing
inputobjs–>1: Object
inputobjs–>2: nothing
inputobjs–>3: nothing
noun: nothing
actor: girl

At this point, the if rule appears to be incorrectly passed. I’m not sure what the correct path is.

I think that the if statement can be simplified. actor ~= player can be factored out, and, if inp1 ~= nothing, the first clause of the || will short circuit, so we know that inp1 == nothing if we reach the second clause.

if (actor ~= player && (inp1 ~= nothing || metaclass(inputobjs-->1) == nothing)) {

Which of the 3 examples that you gave should pass the if? It seems to me that the first and the third won’t, because inp1 is nothing and metaclass of inputobjs–>1 is not nothing, while the second will, because inp1 is not nothing.

The first instance won’t pass the if. This is correct.

The second instance does pass the if, but I’m not sure if that’s correct.

The third instance won’t pass the if. Again, I’m not sure if that’s correct.

I’ve added some debugging print statements. Please see if you divine anything from that output.

I’ve taken a closer look at parserm.h and InformParser::play, and I’m now a little bit confused.

From what I can tell, inputobj–>0 … inputobj–>3 correspond to result–>0 … result–>3 in the parser proper (Parser__parse).

The meaning of these values appears to be:
result–>0 = inputobj–>0 = the action
result–>1 = inputobj–>1 = number of parameters (0, 1 or 2 – intransitive verb, direct obj only, direct and indirect objs)
result–>2 = inputobj–>2 = inp1 = the direct object. if this value is >1, it’s an object and placed in noun. Otherwise, it’s just 1, representing a special value (usually a number), and we get the value of noun from special_number1.
result–>3 = inputobj–>3 = inp2 = the indirect object. if this value is > 1, it’s placed in second. Otherwise, we get the value of second from special_number1 or special_number2 (if special_number1 was used for inp1).

There is one slight variation to this in section H of the parser (“cheaply parse unrecognized conversation”) where an actor has been given a command that’s not understood (girl, blah). In that case, result–>0 is ##NotUnderstood, result–>1 is 2 (meaning 2 params), result–>2 = 1 (with the actual content going in special_number1), and result–>3 = the actor (this is the unusual part). Note that this is consistent with what we’re seeing in your second example above for GIRL, DROP ROCKS (when no rocks are held). It’s obfuscated a bit because the (name) print rule turns 1 into “Class” and 2 into “Object.”

So, given all of that, I don’t understand the purpose of the test for metaclass(inputobjs–>1) == nothing, since inputobj–>1 doesn’t contain an object, but rather an integer count of how many objects the verb has. That would be why its value is always printed as Class or Object, since 1 is the object number of the object representing class Class and 2 is the object number of the object representing class Object.