P32 - Wrong kind of thing bug

I’m getting a runtime error occurring in a pretty microscopic chunk of the game - the time between the line ‘immediately restart the virtual machine’ and one of the first ‘when play begins’ rules. I narrowed it down to that range with error trapping messages.

Inform says:

"P32 - Wrong kind of thing in decide on

When we write a phrase ‘To decide which K is …’, where K is a kind such as door or room, say, any use of ‘decide on X’ inside the definition of that phrase must result in X being the appropriate kind of thing. Here, X turned out to be an object, but an object of the wrong kind."

Before I do painful stuff like go through every extension, see which ones have ‘when play begins’ rules, etc. to further narrow it, I want to ask if there is likely to be any obvious thing to check? And is Inform being literal when it says “When we write a phrase ‘To decide which K is …’”… In other words, can I track this error down by finding a phrase which literally says ‘to decide which such and such is…’ – as opposed to variants like ‘decide on such and such’?

  • Wade

This error check occurs in a “to decide which K is…” phrase definition, at the point of return (“decide on V”). It is also done in rules that have a result type, at the point of return (“rule succeeds with result V”).

Are you using Glulx Entry Points or one of those Glulx window/sound/etc extensions?

Yes, I am using Glulx Entry Points, Flexible Windows and several Glimmr extensions.

  • Wade

That’s where to look, then, as those extensions do work early in the startup sequence.

Thanks much, I will have a look. Though it’s weird this only happens after restarting with the restart command and not when the game first boots. But the startup procedure for this game is kinda complex - in other words, it may run different ‘when play begins’ rules after a restart than it would on initial boot. It checks flags in disk files to work out what to do.

  • Wade

That suggests that something is being reset incorrectly, i.e. that a value is being defined or used differently than it was the first time around. Possibly your complicated startup sequence is accidentally skipping something important?

Hm, I’ve error trapped the bug to occuring before I deliver a single one of my own ‘when play begins’ rules in the source. This suggests to me it happens in the ‘when play begins’ of an extension. So I went through all the extensions. There aren’t actually many ‘when play begins’ rules in them, and some that are there are inoffensive.

The only possible guilty party I could find was Flexible Windows. It has 4 rules:

When play begins (this is the allocate rocks rule): let cnt be 200; repeat with item running through g-windows: if the rock-value of item is 0: set item rock to cnt; increase cnt by 10; now the direct parent of item is the direct-parent of item; set main-window ref.

[code]Section - Validating rock numbers (not for release)

When play begins (this is the rock validation rule):
repeat with item running through g-windows:
let L be the list of g-windows;
remove item from L;
repeat with compared running through L:
if the rock-value of item is the rock-value of compared:
say “***Warning: There appears to be a conflict in the rock numbers of the g-windows ‘[item]’ and ‘[compared]’. Assign all rock-values for custom windows manually to remedy this problem. Avoid using 201 or 202, as these are reserved.”;

When play begins when the main-window is a bordered g-window: apply borders to main-window.

When play begins (this is the initial hyperlink request rule): request glulx hyperlink event in the main-window; request glulx hyperlink event in the status window.

I was able to disable the last rule as a test and run the game, which still worked but still had the bug.

I should point out the status window is formed by splitting the root glk window, thanks to a bit of code by David Kinder. If I understand things right, on an initial boot of the game, this happens in the context of an absence of windows. But after a restart, various windows still exist, even if they’re closed. (I don’t understand why everything isn’t destroyed when the player types RESTART, but I’m not a low level Inform programmer.)

Could the bug be related to the game running through Flexible Windows again on the reboot, and something in there is cranky about the irregular nature of the status window?

  • Wade

That does sound like a possibility. What does your extra code do?

The extension Glulx Status Window Control (which I’m using) has an action in it called ‘initialise the status window’. David Kinder gave me a modified version of that action as follows, which I use in this game:

[code][ This is InitStatusWindow() overriding what’s in “Glulx Status Window Control”, modified to always open the status window by splitting the root Glk window. ]

Include (-
[ InitCustomStatusWindow sty;
if (gg_statuswin == 0) {
statuswin_cursize = statuswin_size;
if ( (+ status window background reversed +) ) {
for (sty=0: sty<style_NUMSTYLES: sty++)
glk_stylehint_set(wintype_TextGrid, sty, stylehint_ReverseColor, 1);
gg_statuswin = glk_window_open(glk_window_get_root(), statuswin_pos, statuswin_cursize, wintype_TextGrid, GG_STATUSWIN_ROCK);

The above is the key to stopping the main window and the map window from ever taking a bite out of the status window, regardless of which order the game’s various windows are opened or closed, or which ones are present or absent at any time.

And, I’m guessing less significantly, DrawStatusLine has been changed so that it no longer makes an initial call to set the status line depth to 1. This stops the status window from flickering on any interpreters and from being constantly resized in general:

Include (- [ DrawStatusLine width posb; @push say__p; @push say__pc; BeginActivity(CONSTRUCTING_STATUS_LINE_ACT); VM_MoveCursorInStatusLine(1, 1); if (statuswin_current) { width = VM_ScreenWidth(); posb = width-15; spaces width; ClearParagraphing(); if (ForActivity(CONSTRUCTING_STATUS_LINE_ACT) == false) { VM_MoveCursorInStatusLine(1, 2); switch(metaclass(left_hand_status_line)) { String: print (string) left_hand_status_line; Routine: left_hand_status_line(); } VM_MoveCursorInStatusLine(1, posb); switch(metaclass(right_hand_status_line)) { String: print (string) right_hand_status_line; Routine: right_hand_status_line(); } } VM_MoveCursorInStatusLine(1, 1); VM_MainWindow(); } ClearParagraphing(); EndActivity(CONSTRUCTING_STATUS_LINE_ACT); @pull say__pc; @pull say__p; ]; -) before "Printing.i6t".

  • Wade

I know it’s still a hassle to set up, but i7grip should tell you which line the problem is on, which might save this guesswork.

It’s possible, but not very likely - that demo project I put together to demonstrate how I fixed things doesn’t seem to show any problems on restart, and all the code was low-level Inform 6, which I wouldn’t expect to cause Inform 7 run-time errors. Of course, you never can tell …

You could always try simply commenting out that code from me. If that fixes it, we can investigate further.

I’ve done a bit more research on this, and I have a somewhat clearer understanding of where things are going wrong, if not precisely why. The culprit is Flexible Windows: a minimal test case to reproduce the problem is

[code]“Test” by David Kinder

Include Flexible Windows by Jon Ingold.

Area is a room.[/code]Run this in the front-end and enter “restart”, and sure enough, you get a Run-time Problem 32 message.

The question of why it only shows up on restart turns out to be interesting. To understand that, we need to bear in mind how the game and front-end interact to produce those Run-time Problem messages: the game prints out a string of the form “*** Run-time problem P…”, which the front-end catches and uses to pick which Run-time message to show in the Errors tab.

Now, on start-up the problem occurs before any Glulx window has been opened, so the game hits the error and tries to print the message, but there’s no window to print the message to, so the message disappears into the ether. Oops! On restart, there is a window, so the message gets printed and seen by the front-end, just before the window is destroyed by the restart process.

I have not yet tracked down what Flexible Windows is doing that causes the error - I will try to look into it when I have a moment. For now, I suggest you just ignore it - it doesn’t seem to cause any problems, and in a released game the message about the problem will never be seen by the user, since either there’s no Glulx window to print it to (on start-up), or the window it’s printed to is destroyed immediately afterwards (on restart).

Thanks tons David, and others who chimed in. It’s a great relief to face the prospect of an extensive bug investigation and then sort of be let off the hook.

  • Wade

Is this with the old Flexible Windows or with my new update?

I was testing with “version 13/130803”.

I’ve just tried “Version 12/110611”, and I don’t see the problem, so something has gone wrong in the changes for version 13.

I’ve been using version 13 with this game of mine. I do remember you (Dannii) saying ‘Here’s a new version’, but I forgot if I downloaded that. Is that 13? If it is, that could also explain why I had previously not been seeing this error, but couldn’t remember a particular moment when it started happening, just because I’ve been working on this project very intermittently. And RESTARTing isn’t something I’d necessarily do every time.

  • Wade

Dannii: I’ve gone through the history of this extension at https://github.com/i7/extensions/blob/master/Jon%20Ingold/Flexible%20Windows.i7x and the problem starts with this commit: https://github.com/i7/extensions/commit/d9a4d1a12f502cb31c1101ec4df1e544f93a3e06 Would you have a look to see where it’s going wrong?

Wade: Dannii’s version of Flexible Windows is version 13. If you want to go back to version 12, you can get it from https://raw.github.com/i7/extensions/838c201011be9e486c431590720a79256a25cbf3/Jon%20Ingold/Flexible%20Windows.i7x

I’ll take a look tomorrow. Sorry for introducing a bug!

To be fair, it is in some frighteningly hairy code!

Okay, I fixed the error, please download the update from github.com/i7/extensions/blob/m … indows.i7x

It was really quite obvious when I looked for it. The problem was it was trying to decide on nothing, which isn’t a g-window!