Request for comment: Thoughts

So, in preparation for my game project, I just built a little system for feeding information to the player gradually. This system defines a number of thought objects, and a rulebook for thinking a particular thought. It allows for sequences of thoughts to unfold one at a time, and unlike the simpler [first time][only] one-shot text functionality, it allows for completely different events to trigger the same thought. It’s fairly simple, but very general-use so I think I’ll put it in an extension, which I might release if there’s interest. This is the implementation I have:

"Morbid Thoughts" by Bruno Dias

The thought preformat is some text that varies. The thought preformat is "[italic type]".
The thought postformat is some text that varies. The thought postformat is "[roman type]".

Thought-state is a kind of value. The thought-states are ending, ended, passing, passed, and repeat.

A thought is a kind of thing. A thought has some text called the content. A thought has a thought-state called the state. The state of a thought is usually ending. A thought has a thought called the next thought.

Some thoughts are defined by the Table of Deep Thoughts.

Table of Deep Thoughts
thought			state			content											next thought
garden thought	ending			"I hate the smell of carnations. I really should go in and
								pay my respects, however."						--
death thought 1	passing			"Well this is depressing."							death thought 2	
death thought 2	passing			"Maybe I should try grief counseling instead."		death thought 3
death thought 3	ending			"I need to stop dwelling on those things."			--

The thinking rules are an object based rulebook.

A thinking rule (This is the thought preformat rule):
	say the thought preformat.

The thought preformat rule is listed first in the thinking rules.

A thinking rule for a thought (called the idea):
	if the state of the idea is ending:
		say the content of the idea;
		now the state of the idea is ended;
	if the state of the idea is passed:
		think the next thought of the idea;
	if the state of the idea is passing:
		say the content of the idea;
		now the state of the idea is passed;
	if the state of the idea is repeat:
		say the content of the idea;
		
A thinking rule (This is the thought postformat rule):
	say the thought postformat.
	
The thought postformat rule is listed last in the thinking rules.

To think (idea - a thought):
	follow the thinking rules for the idea.

To say think (idea - a thought):
	think the idea.

The Carnation Garden is a room. "Ahh, the garden just outside the crypt. [think the garden thought]"

Inside from the carnation garden is the Dank Crypt. The description of the crypt is "Ugh, the crypt." In the crypt are a tomb and a memento mori.

The description of the tomb is "Carved out of marble." The description of the memento is "A skull left upon the tomb as a general reminder of mortality."

After examining the tomb:
	think the death thought 1;
	continue the action.
	
After examining the memento mori:
	think the death thought 1;
	continue the action.

After going in the crypt:
	The grim realisation hits in two turns from now;
	continue the action.
	
At the time when the grim realisation hits:
	think the death thought 1.

Test me with "in / x tomb / z / x memento / x tomb"

This works. I just want to ask if any cleaner/saner/better way of doing this or all of it jumps at anybody, and if you’d like to have it in extension form. Also: This code is recursive because I, not having been a programmer of any sort for years, can’t think of a more elegant way of accomplishing it. It will, however, cause a runtime error if an author using it is careless in defining thoughts. Is there a way to prevent this from happening? Should I try?

I have several comments, which I will post separately.

Have you seen Aaron Reed’s “Experiment 1”?

aaronareed.net/if/ex1/

What you are doing is a little bit like the “symbolizing” relation, although your ability to trigger themes is interesting. Your sequence of thoughts is a little different from the way he implemented the “suggesting” relation, but his experiment shows how relations might be used to do something like what you’re doing.

I thought of using relations, actually, but thought this was simpler to work programatically. The mechanic here isn’t so much that thoughts segue into another - although they could, with a few changes to the code I’ve thought of but haven’t implemented. It’s rather that 1. Thoughts are usually only triggered once, to avoid the protagonist seeming robotic, and 2. An already-triggered thought can be substituted for another. Although this does give me ideas of how to change a couple of things, and how to make this system a bit more interesting by creating default behaviours for thoughts in relation to objects, and making it so the same thought won’t be triggered twice by the same action.

I think the most useful thing to take from Aaron’s experiment is the “theme” object. I think it would be helpful for you to separate themes out from individual thoughts. There are a couple ways you could do this:

Table of Thoughts theme state content garden ending "I hate the smell..." death passing "Well this is depressing" death passing "Maybe I should try..." death ending "I need to stop..."

or…

[code]Table of Garden Thoughts
state content
ending “I hate the smell…”

Table of Death Thoughts
state content
passing “Well this is depressing”
passing “Maybe I should try…”
ending “I need to stop…”
[/code]

It looks like your thoughts are mostly arranged into linear chains. There’s no need to manually implement the links if that’s all you’re going to have. On the other hand, if you want thoughts to converge in a treelike structure, maybe you do need relations or a “next thought” column. Or maybe a “next theme” column?

Anyway, once you have themes, you can give them some useful properties, such as the thoughts-table used by my second example.

If you have a simple chain of thoughts like your “passing” thoughts, you could blank out each row in turn. But if you want to implement a cycle of “repeating” thoughts, you can’t do that. You could, however, give your theme a “current row” or “current thought” property.

In light of this approach, I think you don’t need to distinguish between “passing” and “ending”. It looks like an ending thought is merely a passing thought that has no next thought. You could use “passing” vs “ending” adjectives if you wanted to refer to them in a rule, but it needn’t be explicitly set.

You might consider making the passing/repeating behavior another property of a theme instead of individual thoughts. Then you could use the same random/stopping/etc patterns that say phrases have. And as I hinted before, the “repeating” property could allow you to cycle through a number of thoughts instead of just one.

I love the way you used “some thoughts are defined by the Table of Deep Thoughts.” I didn’t remember you could do that - very useful!

Now a somewhat open-ended question:

Should thinking be an activity or a rulebook? I’ve come across several cases in my own work where I didn’t know which one to use. Most of the time I use a rulebook even when an activity makes sense, because defining and invoking rules is a lot less verbose than doing the same for activities. But the “preformat” and “postformat” rules seem a lot like before activity and after activity rules.

I’d be interested in hearing other people’s views about when activities should be used, or whether they should be removed from the language completely and replaced with rulebooks.

Finally a small complaint:

Line break behavior seems somewhat inconsistent for the code as it stands:

Sometimes there is blank line after the last line in the output, sometimes there is not. And when there is no thought at all, it looks like that can cause a double blank line.

I modded “Experiment 1” to produce prosier prose than what he had, and to let your mind drift a little (in Aaron’s code I think the theme, the last thing everything reminds you of, remains the same unless you wait; in mine it moves one step by the symbolizing relation every turn). What I wound up with produces something that looks to me like a mildly acceptable stream of consciousness on individual turns, but turn by turn it gets very repetitive. One way of dealing with that might be by a rotating table of quips for each theme; I’m not sure how far that would get you toward something that wasn’t obviously generated by procedurally stringing together a bunch of quips. One thing that would definitely help is better writing (though to do that I’d probably have to write my own story).

Anyway, for the curious, it’s below the rant tag. Something like half or maybe more of the code is Aaron’s. Comments not beginning “MW:” are his. If you want to paste this into your IDE, hit the “quote” button and copy out the relevant parts; that should preserve the tab stops. (Thanks to whoever came up with that trick!)

Oh, and I’m still running 5Z; there’s a hack in there to work around a bug that apparently has been fixed in later versions.

[rant][code]“Aaron Reed’s Experiment 1” by Matt Weiner

Use serial comma.

The story description is “Giving objects in a story world symbolic weight has often been done by hand, but rarely procedurally. Here’s one method for doing so.”.

When play begins:
say “Lost in the cold, you can only hope for rescue.”

Include Plurality by Emily Short.

The Wilderness is a room. “The sky is full of stars you could never see in the city.”

Instead of doing something other than looking, taking inventory, examining, and waiting:
say “All you can do is look through your belongings and hope for rescue.”

Instead of taking the compass:
say “It’s broken. It won’t do you any good.”

[MW: The next rule is a hack. For some reason – apparently a 5Z bug – the previous rule triggered when taking inventory. Fortunately I’ve stopped you from changing your inventory, so it doesn’t much matter now.]

Instead of taking inventory:
say "You are carrying ";
list the contents of the player, as a sentence, including contents, giving inventory information;
say “.”

[Let’s imagine a basic story about a young astronomer alone on a backpacking trip. He’s engaged to be married, but is worried about how this will affect his career. He’s also starting to worry that he may be lost, and strange hallucinations make him wonder if he is losing his mind. How might we encode these thematic elements into our story?]

A theme is a kind of thing. being lost, the wild, fear, change, cold, astronomy, what’s really important, career, marriage, and senility are themes.

[MW: Each theme produces different text, something briefer if it’s being used as the transition to another theme, something longer if it’s the last thing that gets mentioned.]
A theme has some text called transition. A theme has some text called resolution.

Being lost has transition "Will you ever get home? ". Being lost has resolution "You wonder whether anyone will ever find you. "

The wild has transition "You’re far from civilization. ".
The wild has resolution "The wilderness is harsh and unforgiving, but you couldn’t live without adventure. ".

Fear has transition "You could die out here. ". Fear has resolution "You start to tremble, not from the cold but from sheer terror that soon you may be dead. ".

Change has transition "And your life is changing. ". Change has resolution "Things will be different when you get back. You’re not sure how, but they will. ".

Cold has transition "How cold it is! ". Cold has resolution "The wind is cutting through your flimsy jacket. You wonder whether you’ll ever be warm again. ".

Astronomy has transition "The stars burn down from the sky, their secrets locked away. ". Astronomy has resolution "You look up at the stars again. Will you ever be able to decipher their secrets? ".

What’s really important has transition "Have you been devoting your life to the right things? ". What’s really important has resolution "When you’re faced with death, you start wonder whether you’ve really been devoting yourself to what’s important. But what exactly is that? ".

Career has transition "You’ve been spending so much time at the observatory. ". Career has resolution "You’ll need to put in some late nights at the observatory when you return – if you return. Your research is at a critical stage. ".

Marriage has transition "Elizabeth – will you ever see her again? ". Marriage has resolution "Soon you’ll be in a new home, married to Elizabeth, always with her. If you survive. How will she cope if you don’t? ".

Senility has transition "You’ve been seeing some strange things here. ". Senility has resolution "You’re not sure whether what you’ve been seeing is real anymore. Is your brain beginning to shut down? ".

[The various things in our story world should connect to these abstract ideas.]

Symbolizing relates one theme (called the metaphor) to one thing. The verb to symbolize (he symbolizes, they symbolize, he symbolized, it is symbolized, he is symbolizing) implies the reversed symbolizing relation.

The player holds a water bottle. The description of the water bottle is “Precious water, the only thing that can keep you alive in the wilderness.” The bottle symbolizes the wild. The player wears a pendant. The description of the pendant is “Elizabeth’s picture; you like to think of it lying next to your heart.” The pendant symbolizes marriage. The stars are a plural-named backdrop. “The stars here are as rich and full as on the mountain peaks.” They are everywhere. They symbolize astronomy. Understand “sky” as the stars. [MW: I typed “x sky” and got “you can’t see any such thing” in a game I was programming myself. Sheesh.] The player wears a jacket. The description of the jacket is “A light jacket, too thin.” The jacket symbolizes cold. A broken compass is here. The initial appearance is “Your broken compass is here.” The description is “Your compass broke and you think you’ve lost the trail.” It symbolizes being lost.

The description of the player is “You’re an astronomer, and right now, you’re lost, cold and worrying that you might be going crazy.”

[What’s interesting, though, is how the themes relate to each other.]

Suggesting relates various themes to each other. The verb to suggest (he suggests, they suggest, he suggested, it is suggested, he is suggesting) implies the suggesting relation.

Being lost suggests fear and the wild. The wild suggests what’s really important and change. Fear suggests change and senility. Change suggests what’s really important and senility. Cold suggests the wild and astronomy. Astronomy suggests career and what’s really important. What’s really important suggests marriage and change. Senility suggests fear. Marriage suggests change.

[Now, we can trace a path of connection between any object in the game world and any theme. Let’s say that, at any point in our story, one theme is dominant.]

The dominant metaphor is a theme that varies.
[Let’s find the connection between any object acted upon and the dominant metaphor.]

Instead of examining:
carry out the finding meaning in activity with the noun.

Finding meaning in something is an activity.

[MW: I’ve changed Aaron’s loop, because the intermediate steps of the chain are different from the first step. Actually if you’re finding meaning in something that symbolized the current theme, it should probably go to its resolution rather than its transition, which is not what happens now.]
For finding meaning in something (called the token):
say the description of the token;
say " ";
let current idea be the metaphor of the token;
if current idea is not a theme:
now the current idea is a random theme;
say the transition of the current idea;
while current idea is not the dominant metaphor:
let the next idea be the next step via the suggesting relation from current idea to the dominant metaphor;
if the next idea is not a theme:
stop;
otherwise if the next idea is not the dominant metaphor:
say the transition of the next idea;
now current idea is next idea;
otherwise:
say the resolution of the next idea;
now current idea is next idea;
advance;
say “[line break]”.

[MW: I wanted to have the PC’s mind wander from theme to theme as he thought; printing the same resolution every turn would be boring.]

Advancing is an action applying to nothing.

To advance:
let the next metaphor be a random theme suggested by the dominant metaphor;
if the next metaphor is not nothing:
now the dominant metaphor is the next metaphor.

[To test this, let’s create a method for setting and revealing the dominant metaphor.]

When play begins: now the left hand status line is “[the dominant metaphor]”.

Carry out waiting: now the dominant metaphor is a random theme.

[Now we have a crude but procedural method of tying any object to any theme, which reveals interesting things about the player character in a way that doesn’t rely on hand-authored text. For instance, examining the stars when the dominant metaphor is “change” finds a path between through “what’s really important,” which reveals that both astronomy and change are important to our protagonist. ]

Every turn:
if the turn count is greater than 5:
say “You hear voices coming from the trail above you, and then you see flashlights and hear someone calling your name. Forgetting everything else, you shout in response, and then your rescuers burst through the underbrush.”;
end the game saying “Saved!”.

[MW: originally I was totes going to have him freeze to death. Also, as you can probably tell, I know nothing about backpacking.]

[/code][/rant]

Something else just occurred to me.

This does look like it might make a good extension, but perhaps it would be good to make it work with Epistemology. In that case you would want to have “subjects” instead of “themes.”

The problematic line breaks are a bug. They’re caused by the pre/postformat rules being invoked even for inactive thoughts, which is something that’s easy to stop. Additionally, the reason for making it a rulebook is so that 1. The if/otherwise logic in that rule can be broken down into separate rules, for cleanliness; 2. The thought-printing logic can be separated from the thought-state changing logic; 3. Additional rules can easily be added by users of the extension, so that thoughts can potentially do more than just print text. For example:

A thought can be sad, happy, fearful or angry. A thought is usually happy.

A thinking rule for a fearful thought (This is the frightening thoughts rule):
	now the player is afraid;
	consider the fright rules.

The frightening thoughts rule is listed before the happy thoughts rule in the thinking rulebook.

(...)

And yes, making it work alongside epistemology should be important. I’ll post a new version of the code as soon as I’m able. Using activities in lieu of rulebooks is a pretty fine point of distinction, as the two are extremely similar.

I would recommend an activity for this for three reasons. One, if you might consider other rulebooks from within thinking, it’ll allow you to write rules like Fright rule while thinking and the like. Two, activities almost never automatically print line breaks, AFAIK, hopefully solving that issue. And three, if you have pre- and post- rules, then yes, you basically using before/after rules by another name.

I had a fourth point, but forgot it already. :blush:

I agree with Sequitur that being forced to put all the heavy lifting into one rule for doing an activity makes it an unattractive choice. Does the “while thinking” clause allow you to tack extra rules on there? Does it defeat the purpose if a rule for doing an activity considers a rulebook, or does that reintroduce the line break problems?

It also occurred to me that there’s no problem having both “themes” and “subjects.” Epistemology keeps track of all things, so both would be covered. Of course, a theme could be a kind of subject - I don’t think it matters much, although that would make it “usually familiar”.

Actually, I plan on moving over to subjects, mainly for the reason that subjects can (With Eric Eve’s conversation framework) be talked about as well. thus allowing for an object that can be both a thought triggered by experiences and a subject in conversation. Also: The erratic spacing was, as I thought, the consequence of the game running the pre- and post-format rules no matter whether a thought was actually being printed. This is fixed by defining ‘active’ thoughts and ensuring those rules only run for active thoughts; now the spacing isn’t ideal (Mostly as a consequence of how the thinking rules can be called from anywhere) but it is consistent.

That’s exactly what I’m talking about. The quizzing and informing actions apply to things - they can be actual concrete things in the game-world, or abstract things like subjects, or new kinds of things that you define yourself, like themes. A subject is a convenient way of creating an abstract known thing, but it’s by no means the only way.

Ahh, true, I forgot that part. Well then. Still, using a subtype of subjects is probably ‘neater,’ keeping all our abstract ducks in a row.