Bold type in a string variable

I’m not sure why this isn’t working as intended so thought I would ask on here.

I’m building a string variable that reports where an item has been placed by random choice.

Now PlacementString is "has been placed in [Bold type][Weapon Item Location entry]";

The reason i’m building it as a variable as opposed to simply saying it is it’s part of a process not yet finished so this string will be said later on…

this is the code later on…

say "A [ItemType], [bold type][ItemName][Roman type], [PlacementString]";

ItemType is a string that dictates what type of item (weapon,tool, etc)
ItemName is the printed name of the item.

So an example of what that say would look like in game:

A Weapon, Knife, has been placed in Kitchen.

The problem is Kitchen is supposed to be Bold, to emphasise the room it went in, and if you look at my string variable it has [Bold type] set.
But when the string is later displayed as part of the larger say command, the bold doesn’t work.
so it ends up looking like:

A Weapon, Knife, has been placed in Kitchen.

It’s a small issue for sure, but it’s got me wondering why font styles don’t work in variables, and how to work around that to get it to work.

I would understand if variables didn’t understand font styles and just reported them literally, for example:

A Weapon, Knife, has been placed in [Bold Type]Kitchen.

But it doesn’t show the code…it recognises it as a special bit of text…however it simply doesn’t do it!

Any ideas?

Variables don’t understand font styles, so the text generation code drops that information when filling in the variable.

There are various ways to get the right results here. They basically boil down to “don’t use a text variable”. Use more variables (maybe placement-item and placement-location) and generate all the text, with appropriate styles, at the end.

i’d pretty much come to the same conclusion.
The issue is that the sentence contained within PlacementString changes depending on where the item is set to be placed.

Now PlacementString is "has been placed in [Bold type][Weapon Item Location entry]";

or

Now PlacementString is "will be in the player's inventory";

The idea being, instead of having if statements that check inventory or room, the string is built as the item’s placement is decided and then the result is simply said later with one say as opposed to multiple say’s depending on location.

My solution to the bold problem was to split that string up like you said.

if the item gets placed in a room…

Now PlacementString is "has been placed in ";
Now ItemLoc is Weapon Location entry;

The say sentence later:

say "A [ItemType], [bold type][ItemName][Roman type], [PlacementString][Bold type][ItemLoc]";

If the item ends up being given to the player, I blank out the ItemLoc variable, so if the setence ends up being:

will be in the player's inventory

Then even though the [bold type][ItemLoc] will still come after it, because there is no text in that string, it doesn’t disturb the sentence in any way.

More specifically, the critical issue is when the text substitution actually takes place. A text variable can successfully hold text awaiting substitution, including font styles, so long as the substitution only eventually happens at the point of saying. If text is forced into being stored in the text variable in its substituted form, then the formatting will be lost.

e.g.

TestText is a text that varies.
When play begins:
	now TestText is "If I may be so [bold type]bold[roman type]?".
	
Printing is an action applying to nothing.
Understand "Print" as printing.
Carry out printing: say "I beg your pardon. [TestText]".

which works just fine, so I think the essential problem being highlighted in the original post is that PlacementString is being forced into its substituted form ahead of time, possibly because one of its component substitutions is dependent on a local variable which is going out of scope before it is ‘said’.

Funny you say that, because it does just so happen that the text failing to go bold is a Table entry grab.

Now PlacementString is "has been placed in [Bold type][Weapon Item Location entry]";

[Weapon Item Location entry] being a table entry that holds the room name to be displayed in the string.
So you’re saying something happens later after the above declaration to cause the boldened entry ref text to change which causes the Bold to become unset?
If so, i’m not sure how/when/why that would be happening as i’m never touching either PlacementString itself or the table entry between the creation of, and eventual saying of, that string.

EDIT:
I think I may understand what might be the issue.
So the above Now statement is part of a ‘repeat through’

it repeats through the table, finds the room for the item and writes the room name into the string.

However, the string is said later, in the same action, but outside the repeat through where, although the text is locked into the variable as what the entry was, the actual entry itself is not valid anymore because that part of the code is no longer repeating through a table.
Table entries only being accessible and valid references while repeating through.

Assuming that is indeed the cause of the issue I was encountering, and assuming I wanted to revert back to doing it all in one string as opposed to my two variable solution (see my second reply), 'm guessing i’d need ‘the substituted form of [Weapon Item Location entry]’?

If so, this leads me to another question I have regarding strings.
How do you use ‘the substituted form of [variable]’ in a string or say that also contains quoted text?

say "I am standing in the substituted form of [Weapon Item Location entry]";

That’s clearly going to write that all out literally, rather than actually do the substituted form.
In other languages you can usually go in and out of strings.

Ex:

NewString = "The room I am standing in is " + RoomPlayerIn; [RoomPlayerIn being a variable ref]

is there the equivalent of the above in Inform?

One way I sort of got working last night was to do something along these lines:

Now String is "This is text that is static and doesn't change but ";
Now String is "[String] the next part might not be!"; [this in theory adds the second half onto the above line]

In theory that worked, and for one case of that in my code it worked, however Inform didn’t really like it because it kept causing a stack overflow error whenever it tried to say the result.

Unfortunately, that is the opposite of what is going to help you here. 'The substituted form of “[something]” ’ is a means of forcing the text substitution to take place right away (with the result stored in a variable) and thereby fixing it to the current expansion of “[something]” (and coincidentally losing any formatting). This can be useful when whatever variables or data “[something]” is dependent on needs to be what it is now, rather than when it may have changed to by the time “[something]” is said.

Inform forces an immediate substitution even without the use of ‘the substituted form of’ when it realises that the variables/data “[something]” depends on will no longer be accessible when the variable it is stored in is ‘said’. This is most often the case for text expansions dependent on local variables (discussed in Writing With Inform 20.7). I think your analysis of why immediate substitution is forced in your case- a reference to ‘a table entry in the current row’- is correct.

There’s no easy way I can immediately see to maintain a reference in substituted text to a table entry without forcing an immediate substitution. Even ‘the (target column name) corresponding to the (index column name) of (index)’ is not available, because the reference to (index) can’t be embedded in a text substitution, which disallow nested substitutions.

However 'now (global_text_variable_1) is (the_entry_of_interest); now (global_text_variable_2) is “some text or other[bold type][global_text_variable_1][roman type].”… some time later… say global_text_variable_2…or… say “some other text [global_text_variable_2]” ’ should work.

In general programming terms, it sometimes helps to think of texts containing expansions such as “[something]” as routines that return a string (which, in the I6 translation of the I7 source, is what they actually are).

Consequently 'Now String is “[String] some text” sets up a classic endless recursion when String is ‘said’, i.e. the routine is called and recursively keeps calling itself.

This can be avoided by "Now String is the substituted form of “[String] some text”, as now String is stored as plain text not as a recursive routine. But it won’t preserve any formatting, as explained above.

You can happily store substitutions (i.e. routines returing text) in text variables to be run (‘said’) later as long as they are not self-referential. So 'Now String A is “[String B] some text [String C] some text [String D]” will be fine so long as String B, String C and String D don’t themselves reference String A.

The equivalent form of this in Inform is the one you have struck upon yourself, i.e.

Now NewString is "The room I am standing in is [RoomPlayerIn]";

Thanks for all the help Peter.
It’s most informative (no pun intended).

My example with NewString was a bit simplistic because obviously:

Now NewString is "The room I am standing in is [RoomPlayerIn]";

is the way to put variables mixed in with strings.
I’m just not sure how you do substituted form in a single mixed variable.

One way, involving three strings would be:

Now StringA is "The key is located in the ";
Now StringB is the substituted form of [KeyLocation]; 
Now StringC is "[StringA][StringB]";

In the interest of minimalization, it would be nice to simply put that all into StringA.
Hence the example I used:

StringA = "The key is in " + the substituted form of [KeyLocation];

The parts in quotes are recognised as text, the parts out of the quotes and after the + are recognised as machine code and acted upon.

Obviously that’s not correct Inform code syntax, but that’s more what I was getting at.
is there a way to use “the substituted form” within the same string as quoted text or can it only be done via seperate variables combined?

My immediate guess would be:

Now NewString is "The room I am standing in is [the substituted form of [RoomPlayerIn]]";

But now you have brackets within brackets which Inform does not like so i’m going out on a limb and assuming that wouldn’t work.

EDIT:
Re-Reading your posts i’m assuming the answer is to build the string using the substituted form command.

Example:

Now NewString is the substituted form of "The key is located in [KeyLocation]";

My mistaken assumption was “the substituted form of” immediately needed a variable and only a variable as part of it’s parameter.
But you just write the text before or after.
Correct?

Correct, this will build a substituted string, but it won’t preserve text formatting. To do that you need to avoid storing the substituted form of a substituted text in a text variable. You need to store the unsubstituted form in a global text variable.

Great!

In regards to substituted forms losing font formatting, that’s fine.
I was more just wondering how you even go about combining substituted forms alongside handtyped text so it’s good to finally know that.

As for the issue at hand with the Bold table entry, it sounds like the solution I ended up using in the end in my second post of this thread is the way to go because it falls pretty much in line with your suggestion.

Two variables…one that has the first part of the sentence, and then a variable that stores the table entry…the say later combines the two strings and specifies [bold type] just before [variable2].

Subtly different, because in this case the formatting of the variable is not a characteristic of the variable itself but hard-coded into the final ‘say’ phrase.

E.g. the difference between

KeyLocation is a room that varies.
...
Now KeyLocation is Dungeon.
...
say "The key is located in [bold type][KeyLocation][roman type].".

(your method)

vs

KeyLocation is a text that varies.
...
Now KeyLocation is "The key is located in [bold type][Dungeon][roman type]".
...
say "[KeyLocation].".

Or, to expand to something closer to your original code:

Now ItemType is Weapon.
...
Now ItemName is Knife.
...
Now ItemLocation is Dungeon
...
say "A [ItemType], [bold type][ItemName][Roman type], has been placed in [bold type][ItemLocation][roman type].".

(your method)

vs

PlacementString is a text that varies.
...
Now ItemType is Weapon.
...
Now ItemName is Knife.
...
Now ItemLocation is Dungeon
...
Now PlacementString is "has been placed in [bold type][ItemLocation][roman type]".
...
say "A [ItemType], [bold type][ItemName][Roman type], [PlacementString]".

Depending on your needs, either approach or both will work.

Actually, I was wrong here- the name of the index variable doesn’t of course need its own expansion within square brackets (Doh!) :grimacing: the reference to a table entry ‘looked up’ via ‘the (target column name) corresponding to the (index column name) of (index) in (table name)’ can therefore be maintained in a stored unsubstituted text variable so long as (target column name), (index column name), (index) and (table name) are either given directly or are global variables/constants.

"Hamster Care" by PB

Lab is a room. The hamster is an animal in the Lab. The activity chart is a fixed in place thing in the Lab. "A peeling and faded chart hangs limply above [regarding the hamster][possessive] cage.".

Instead of examining the chart: showme the contents of the Table of Hamster Activities.

Response_Text is initially "[Activity_Time] is time for [bold type][the Activity corresponding to the Time of Activity_Time in the Table of Hamster Activities][roman type].".
Activity_Time is initially 9:00 AM.
Activity_Type is initially "Exercising".

Instead of waiting for the first time:
	say Response_Text;
	now Response_Text is  "[bold type][Time corresponding to the Activity of Activity_Type in the Table of Hamster Activities][roman type] is time for [Activity_Type].".
	
Instead of waiting for the second time:
	say Response_Text;
	now Activity_Type is "Sleeping";
	
Instead of waiting for the third time:
	say Response_Text;

Table 1.1 - Hamster Activities
Time (time)	Activity (text)
9:00 AM	"Feeding"
12:00 AM	"Exercising"
5:00 PM	"Sleeping"

Test me with "x chart / z / z / z".

PS if you do want to be able to write things like

StringA = "The key is in " + the substituted form of [KeyLocation];

in Inform, it’s easy enough to set up:

To decide which text is (T1 - a text) + (T2 - a text): decide on "[T1][T2]".

T1 and T2 can either be plain text, or a routine that returns a text (i.e. a text with substitutions)