I’ve been working on code for a similar issue in my WIP. It turns out it’s tricky because when you UNDO an action, the room name is printed by some I6 code, and ends up in lower case instead of title case. I came up with an I6 inclusion to work around that, but it’s kind of gross. If anyone can suggest a more elegant/future-proof/sane method, I’d be much obliged.
[code]Section - Printing the name of a room
[If the name of a room is printed in some ordinary text, it should be printed as, e.g. “the nursery”, not just “Nursery”.]
A room has some text called the lower case name.
The lower case name of a room is usually “the [printed name of the item described in lower case]”.
[Some rooms, e.g. the Sunday School room, might need some upper case letters in their lower case name, or might need a more complicated lower case name, or something. We can fix them by giving them the appropriate lower case name.]
Rule for printing the name of a room (called the place):
if the constructing the status line activity is going on or the current action is looking or currently undoing is true:
say “[printed name of the place]”;
otherwise:
say “[lower case name of the place]”.
[Apparently the only way to figure out if we’re in the middle of undoing a command is to replace a bunch of I6 template code with a new version including just a couple of trivial changes? Okay then.]
Currently undoing is a truth state that varies. Currently undoing is false.
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
(+ currently undoing +) = true; ! now we're undoing a thing, possibly
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;
}
(+ currently undoing +) = false; ! we've finished undoing a thing
return nw;
}
];
-) instead of “Reading the Command” in “Parser.i6t”.[/code]
I was looking at it again just now and wondering if it might be better to replace SL_Location instead of Keyboard, but it looks like then I’d have to copy-paste a bunch of other I6 functions from that section of the templates, just to change one of them? I can’t decide if that’s more or less terrible than replacing Keyboard (probably less?). I really don’t know enough about what goes on under I7’s bonnet, I’m just flailing about here.