Telling whether two objects have the same name within an I6 inclusion

Name construction and text construction both being so complicated, all I’ve come up with to be able to test two objects having the same name in I6 is using an I7 function from I6.

to decide if (o1 - object) is cognominal with (o2 - object) (this is cognominality):
  decide on whether or not "[o1]" is "[o2]". [ in current development Inform, string comparison does `substituted form` automatically ]

To decide if i6test (o1 - object) and (o2 - object):
(- ((+ cognominality +)-->1)({o1},{o2}) -)

anyone have a better way, ideally a pure I6 way? I assume there’s something clever that could be done with capturing the printing of the name in a Glk stream…

1 Like

Well, they’re stored as I7 texts, so I imagine TEXT_TY_Compare would do it, right?

Of course, that would only let you check the text stored in a property (like the printed name), not any fancy “rule for printing the name of” effects. For those you’d want I7.

Just to clarify: What exactly do you mean by “the same name” in your question?

Your code compares substituted forms of the printed name (without articles). This means any variations on printed name due to activity rules and the like would potentially intervene. Is that OK? Also, is there any chance that one of the two objects would be the player, and, if so, do you want “yourself” to be that object’s name? Also, do you care only about the printed name or does it matter how the player can refer to the objects?

I personally like to take advantage of I7 from I6 when possible, but if TEXT_TY_Compare() doesn’t work, you can do the comparison the hard way by using PSN__(obj) (which invokes the printing the name activity) to print the current names to memory buffers then make a byte comparison. (If “yourself” matters, then STANDARD_NAME_PRINTING_R(obj) instead.)

My heart is set on the name as printed by the printing the name activity here. I’m good with excluding the player from consideration as one of the objects.

That sounds great…

ok, some quick cribbing from Eric Eve’s Capture Text later…

lab is a room.
dog is an animal. printed name is "lab".

when play begins:
cogtest player and lab;
cogtest lab and lab;
cogtest dog and lab;

to decide if (o1 - object) is cognominal with (o2 - object): (- NameEq({o1},{o2}) -)

to say object id (o - object): (- print {o}; -)

to cogtest (o1 - object) and (o2 - object):
  say "[object id o1] named |[o1]| is [unless o1 is cognominal with o2]not [end unless]cognominal with [object id o2] named |[o2]|.";

to initialize name buffers: (- NBUF1-->0 = TEXT_TY_BufferSize; NBUF2-->0 = TEXT_TY_BufferSize; -)

this is the name buffer initialization rule: initialize name buffers.

the name buffer initialization rule is listed in the after starting the virtual machine rules.

Include (-
Array NBUF1 --> TEXT_TY_BufferSize;
Array NBUF2 --> TEXT_TY_BufferSize;

[ NameCapture obj buf old_stream new_stream len;
len = buf-->0;
@mzero len buf;
old_stream = glk_stream_get_current();
new_stream = glk_stream_open_memory_uni(buf + WORDSIZE, TEXT_TY_BufferSize, 1, 0);
glk_stream_set_current(new_stream);
PSN__(obj);
glk_stream_set_current(old_stream);
@copy $ffffffff sp;
@copy new_stream sp;
@glk $0044 2 0; ! stream_close
@copy sp len;
@copy sp 0;
buf-->0 = len;
];

[ NameEq o1 o2 i;
if (o1 == o2) rtrue;
NameCapture(o1, NBUF1);
NameCapture(o2, NBUF2);
for ( i = 0 : i <= NBUF1-->0 : i++ ) if (NBUF1-->i ~= NBUF2-->i) rfalse;
rtrue;
];
-)

produces

551230 named |yourself| is not cognominal with 551262 named |lab|.
551262 named |lab| is cognominal with 551262 named |lab|.
551294 named |lab| is cognominal with 551262 named |lab|.

Of course, since you’re invoking an I7 activity for this, whether this is really any more elegant than calling an I7 phrase is left to the reader.

Loading and comparing two plain text buffers and noping out immediately if they’re different lengths or as soon as a discrepancy is found otherwise is going to be a lot faster than constructing and comparing two I7 texts. This is for use in a loop that’s going to get hit a lot.

1 Like

@OtisTDog tipped me off to VM_PrintToBuffer, so now it’s down to:

[ StringEqualObjectNames o1 o2 i;
  VM_PrintToBuffer(NBUF1, TEXT_TY_BufferSize, PSN__, o1);
  VM_PrintToBuffer(NBUF2, TEXT_TY_BufferSize, PSN__, o2);
#ifdef TARGET_GLULX;
  for ( i = 0 : i <= NBUF1-->0 : i++ ) if (NBUF1-->i ~= NBUF2-->i) rfalse;
#ifnot;
  if (NBUF1-->0 ~= NBUF2-->0) rfalse;
  for (i = WORDSIZE : i < ((NBUF1-->0) + WORDSIZE) : i++ ) if (NBUF1->i ~= NBUF2->i) rfalse;
#endif;
  rtrue;
];
1 Like

You’re not checking the lengths are the same in Glulx?

I am, but in Glulx it can happen as part of the loop.

1 Like