Remapping the blank command to wait

I wanted to remap a blank command from the player to wait, but neither “after reading the player’s command” nor “before printing a parser error” seem cooperative. I can fake wait - the game claims that time passes, but it doesn’t, even with an explicit command to follow the every turn rules.

Smarter Parser seems to fake progression as well, which suggests that this behavior is hardwired. Can I get confirmation on that?

I think… For printing a parser error when the latest parser error is the I beg your pardon error: try waiting instead. should do it.

Hmm. Using 6G60, the time at the end of this code is only 9:01 am. Do you get something different?

[code]“Test” by Gravel

Testing is a room.

Every turn:
say “It is now [time of day].”

For printing a parser error when the latest parser error is the I beg your pardon error: try waiting instead.

Test me with “z / / / z”[/code]

How about (untested) waiting and then abiding by the advance time rule?

That seems related to the issue I had with this bug, and that was my fix.

oh, time isn’t advancing. I misunderstood the missing piece. (And thought that was fixed in any event.) Try adding this: out-of-world is a truth state that varies. The out-of-world variable translates into I6 as "meta".
And then stick in a now out-of-world is false; right before the Try statement.

Well that’s a lot more convenient than trying to solve this sort of problem by kludging around in I7. Thanks!

I like that! It looks much better than trying to “follow the turn sequence rules” or whatnot. Very useful.

Actually, it looks so useful that I wouldn’t mind it being added to the language: whenever trying an action that is not out-of-world, the “meta” variable should be set to false. Anyone got votes on Uservoice?

I see what’s supposed to happen with out-of-world, but it isn’t working for me.

Matt’s solution seems to in combination with firing the every turn rules, although I admit that I’m a little anxious that some vital piece is getting left out along the way. I guess we’ll find out along the way!

For printing a parser error when the latest parser error is the I beg your pardon error: try waiting; follow the every turn rules; abide by the advance time rule.

If I were doing this, I would write an after-reading-command rule to replace the blank line with “wait”. That will keep things in the normal command path, which means you don’t have to sort through the issues that you’ve been sorting through.

EDIT-ADD: Duh, you tried that and of course it doesn’t work, because that path short-circuits. Well, I’d apply the necessary I6 hacking to avoid that. Sorry about the uglier-than-I-thought suggestion.

Zarf, that was my first attempt, too. The issue with that is that the after reading a command doesn’t seem to fire at all when the command is blank - it skips straight to the “I beg your pardon” parser error.

Here it is, the whole mess, put between spoilers because it is long. If you want to use it, quote this topic and copy-paste the code from there: that way you’ll actually get all the tabs. (Indenting the Inform 6 code by hand is a pain.)

[spoiler][code]After reading a command:
let T be indexed text;
let T be the player’s command;
if T is “”:
change the text of the player’s command to “z”.

Include (- [ Keyboard a_buffer a_table nw i w w2 x1 x2;
sline1 = score; sline2 = turns;

while (true) {
	! Save the start of the buffer, in case "oops" needs to restore it
	for (i=0 : i<64 : i++) oops_workspace->i = a_buffer->i;

	! In case of an array entry corruption that shouldn't happen, but would be
	! disastrous if it did:
	#Ifdef TARGET_ZCODE;
	a_buffer->0 = INPUT_BUFFER_LEN;
	a_table->0 = 15;  ! Allow to split input into this many words
	#Endif; ! TARGET_

	! Print the prompt, and read in the words and dictionary addresses
	PrintPrompt();
	DrawStatusLine();
	KeyboardPrimitive(a_buffer, a_table);

	! Set nw to the number of words
	#Ifdef TARGET_ZCODE; nw = a_table->1; #Ifnot; nw = a_table-->0; #Endif;

	! If the line was blank, get a fresh line
	!if (nw == 0) {
	!	@push etype; etype = BLANKLINE_PE;
	!	players_command = 100;
	!	BeginActivity(PRINTING_A_PARSER_ERROR_ACT);
	!	if (ForActivity(PRINTING_A_PARSER_ERROR_ACT) == false) L__M(##Miscellany,10);
	!	EndActivity(PRINTING_A_PARSER_ERROR_ACT);
	!	@pull etype;
	!	continue;
	!}

	! Unless the opening word was OOPS, return
	! Conveniently, a_table-->1 is the first word on both the Z-machine and Glulx

	w = a_table-->1;
	if (w == OOPS1__WD or OOPS2__WD or OOPS3__WD) {
		if (oops_from == 0) { L__M(##Miscellany, 14); continue; }
		if (nw == 1) { L__M(##Miscellany, 15); continue; }
		if (nw > 2) { L__M(##Miscellany, 16); continue; }
	
		! So now we know: there was a previous mistake, and the player has
		! attempted to correct a single word of it.
	
		for (i=0 : i<INPUT_BUFFER_LEN : i++) buffer2->i = a_buffer->i;
		#Ifdef TARGET_ZCODE;
		x1 = a_table->9;  ! Start of word following "oops"
		x2 = a_table->8;  ! Length of word following "oops"
		#Ifnot; ! TARGET_GLULX
		x1 = a_table-->6; ! Start of word following "oops"
		x2 = a_table-->5; ! Length of word following "oops"
		#Endif; ! TARGET_
	
		! Repair the buffer to the text that was in it before the "oops"
		! was typed:
		for (i=0 : i<64 : i++) a_buffer->i = oops_workspace->i;
		VM_Tokenise(a_buffer,a_table);
	
		! Work out the position in the buffer of the word to be corrected:
		#Ifdef TARGET_ZCODE;
		w = a_table->(4*oops_from + 1); ! Start of word to go
		w2 = a_table->(4*oops_from);    ! Length of word to go
		#Ifnot; ! TARGET_GLULX
		w = a_table-->(3*oops_from);      ! Start of word to go
		w2 = a_table-->(3*oops_from - 1); ! Length of word to go
		#Endif; ! TARGET_
	
		! Write spaces over the word to be corrected:
		for (i=0 : i<w2 : i++) a_buffer->(i+w) = ' ';
	
		if (w2 < x2) {
			! If the replacement is longer than the original, move up...
			for (i=INPUT_BUFFER_LEN-1 : i>=w+x2 : i-- )
				a_buffer->i = a_buffer->(i-x2+w2);

			! ...increasing buffer size accordingly.
			#Ifdef TARGET_ZCODE;
			a_buffer->1 = (a_buffer->1) + (x2-w2);
			#Ifnot; ! TARGET_GLULX
			a_buffer-->0 = (a_buffer-->0) + (x2-w2);
			#Endif; ! TARGET_
		}
	
		! Write the correction in:
		for (i=0 : i<x2 : i++) a_buffer->(i+w) = buffer2->(i+x1);
	
		VM_Tokenise(a_buffer, a_table);
		#Ifdef TARGET_ZCODE; nw = a_table->1; #Ifnot; nw = a_table-->0; #Endif;
	
		return nw;
	}

	! Undo handling

	if ((w == UNDO1__WD or UNDO2__WD or UNDO3__WD) && (nw==1)) {
		Perform_Undo();
		continue;
	}
	i = VM_Save_Undo();
	#ifdef PREVENT_UNDO; undo_flag = 0; #endif;
	#ifndef PREVENT_UNDO; undo_flag = 2; #endif;
	if (i == -1) undo_flag = 0;
	if (i == 0) undo_flag = 1;
	if (i == 2) {
		VM_RestoreWindowColours();
		VM_Style(SUBHEADER_VMSTY);
		SL_Location(); print "^";
		! print (name) location, "^";
		VM_Style(NORMAL_VMSTY);
		L__M(##Miscellany, 13);
		continue;
	}
	return nw;
}

]; -) instead of “Reading the Command” in “Parser.i6t”.[/code][/spoiler]

oh you’re right; it doesn’t work. That’s surprising cause i use that trick in Understand…as a mistake.

I’ll poke around with it some more and see what’s going on.

The every turn rules are never encountered, because “try” only fires the action rulebooks. (Before, Instead, Check, and so on.) Meanwhile, we’re still within the “parse command rule” in the turn sequence rules.

This works great! Thanks much; it’s nice to know straight up there’s no difference between a wait and a blank line entry.

Hey Victor,

Will your quoted routine work for any command of the author’s choice? For instance, I’d like to remap a blank entry to ‘again’. I tested this and it seems to work fine, but since I don’t understand the I6 code you wrote, I wondered if there was anything specific about it that makes it safe for ‘wait’ only, as per your original example?