Indexed text loses formatting information

Hi everyone –
I’m very new to Inform, and I must say I’m having a blast with it. Unfortunately I seem to be doing things the wrong way and/or being too demanding of the system (most likely the former).

The design goal I had in this particular scene is to have certain texts change dynamically according to a global state. That is, performing actions on certain objects would output some constant base text – but as the player performs these actions, each printout would get more and more “corrupted”. The “corruption level” is a property of The Stasis, our current scene. This value is incremented whenever a trigger action occurs.

To achieve this text behavior, I made a new phrase called “corrupted say”:

To corrupted say (original - indexed text):
	Let replacements be words in row (corruption level of the stasis) of the Table of Word Substitutions;
	Let count be number of words in original;
	Let already-chosen be {0};
	Repeat with rep running through replacements:
		Let ran be 0;
		While ran is listed in already-chosen: [no duplicates]
			Let ran be a random number from 1 to count;
		Add ran to already-chosen;
		Replace word number ran in original with rep;
	Say original;

This is pretty slow. But that’s not what bothers me – it’s the fact that all my formatting is gone! In text passed to this phrase (“original”), I want to use things like [italic type]. As soon as indexed text is used, this is eradicated from the world.

Furthermore, when using Parchment, even [paragraph break] doesn’t work. Instead, I get two asterisks **.

I tried using regular expressions to add my own symbols for paragraph breaks and have them Say’d. This slows things down greatly, and I was using up all the memory.

Is there a more elegant way to achieve this? If it were just one object being “corrupted”, I could probably use [say phrases].

Thanks for your help!!

I think the problem with asterisks has been fixed in the most recent version of Parchment.

Styles are a more serious problem. As you discovered, indexed text is simply a list of characters, and doesn’t support any kind of style information.

A possible idea: rather than indexed text, use a list of (ordinary) text, containing one per word. Use special words ("$ITALIC$", “$NORMAL$”) for style markers. You can write a routine to print such a list efficiently, because comparing ordinary texts is fast. It will also be efficient to alter single words in the list.

Unfortunately this will be a nuisance to set up. You’ll have to write code like {“This”, “is”, “the”, “$ITALIC$”, “room.”, “$NORMAL$”}.

What’s the algorithm for “change the nth word to …”? If it doesn’t have any means of caching progress, then going over the full string will be O( (number of letters) * (number of words) * (cost of looking up a word) ).

For a speedup, how about:

  • Put the text to be changed into one indexed text.
  • Put the changed text into a second indexed text (or use StreamToArray or whatever it’s called).
    That’ll knock the cost down to O ( (number of letters) + (number of words) * (cost of looking up a word) )

To deal with formatting codes, would this work:

  • Declare an activity “Capturing Text to be Corrupted”
  • Add say phrase To say bold type while Capturing Text to be Corrupting is going on: say “$BOLD$”.

Perfect, it sure does. Thanks!! As for your text list solution, maybe I could automate generating that somehow, with an external script perhaps.

Thanks for the reply! I don’t know how “Change the nth word to …” is implemented. It comes standard with Inform. I think the slowdown comes from using indexed text in general. Every consecutive run gets slower and slower.

I think I understand what you mean with the “Capturing” idea, but I don’t know what I would do with an indexed text with $BOLD$ in it. I’d be back at square one with chopping indexed texts up and saying them.

I have an extension called Output Filtering on the Inform site which has a section of code that does this. You might be able to steal and modify that.

Just an idea.

It’s not so much “indexed text” is slow as “doing certain things with indexed text” is slow, and you’re doing some of those slow things.

For example, inserting a character in the middle of the string will force it to copy over every character after that.
Finding the nth word may well force it to count through every character up to that point.
Finding word 1, then finding word 2, … then finding word 50, will force it to iterate through most of the string many times.

With my method, you’ll iterate over each character once. And just before the final output, whenever you hit a $, scan forward until you hit the next $, then call the appropriate function based on whatever was in the middle.

This is pretty incredible!
It works great. Fast and easy (well, faster at any rate). And paragraphs and formatting are preserved.