Thoughts
The thoughts.t module provides a framework for responding to commands of the form THINK ABOUT WHATEVER, and for customizing responses to a bare THINK command. For the former, it uses precisely the same TopicEntry mechanism as the Consultable/ConsultTopic classes, and can be used in almost precisely the same way. All you need to do is to define an object of the ThoughtManager class and then populate it with Thought objects, like so:
myThoughts: ThoughtManager ; + Thought @george "To be honest, you're not really sure what he's doing here. " ; + Thought @tFire "It's a wretched nuiscance. Your nephew's probably to blame for it somehow, but the important thing right now is just to escape from it. " ; + DefaultThought "You find your thoughts start to wander; for some reason you can't concentrate on that topic right now. " ;
Thought inherits from TopicEntry, so you can use all the properties and methods of TopicEntry with it; Thought and DefaultThought work just like ConsultTopic and DefaultConsultTopic.
You can exclude thoughts.t if you don't want to implement a THINK ABOUT command (or you don't want to implement it this way), but if you include thoughts.t you must also include topicentry.t.
Thoughts and thinkDesc
Responses to THINK ABOUT may also be defined using the thinkDesc property of a Thing or Topic. If a matching Thought has been defined, it will take precedence over the thinkDesc. The thinkDesc property will be used only if:
- No ThoughtManager object has been defined in the game; or
- A DefaultThought has been defined under the ThoughtManager object and no Thought handles the THINK ABOUT command.
In the event that a ThoughtManager object has been defined in the game, it is the DefaultThought that will attempt to find a matching thoughtDesc. If no matching thoughtDesc exists, the DefaultThought will use its topicResponse as usual.
Defining thoughtDesc on Things and Topics may be more convenient than defining a series of Thoughts, but it may also prove less flexible (e.g., where thoughts about a given topic vary according to circumstances). Game authors are free to mix and match both approaches. For example a Thought could have an isActive property which becomes true only under certain circumstances. When its isActive property is true, the Thought will be used to respond to the THINK ABOUT command but when it is nil the DefaultThought will try to use the relevant thinkDesc instead.
Thoughts with Multiple Player Characters
If the player character changes during the course of your game, you may want to define a different set of Thoughts for each actor who might become a Player Character. To do this you need to define a thoughtManager
object for each (potential or actual) player character and set its thinker property to the actor whose Thoughts will be located under it, for example:
myThoughts: ThoughtManager thinker = me ; + Thought @george "To be honest, you're not really sure what he's doing here. " ; + Thought @tMavis "You rather like her. " ; + Thought @tFire "It's a wretched nuiscance. Your nephew's probably to blame for it somehow, but the important thing right now is just to escape from it. " ; + DefaultThought "You find your thoughts start to wander; for some reason you can't concentrate on that topic right now. " ; georgeThoughts: ThoughtManager thinker = george ; + Thought @tFire "A nasty hazard, in your opinion." ; + Thought @tMavis "You can't stand her. " ;
What happens behind the scenes here is that the preinitialization of any ThoughtManager object will set the myThoughtManager property to itself on the Thing defined on its (the ThoughtManager's) thinker property. If thinker is nil
it will assume that the owner of the thoughts is the initial player character. The setPlayer() function then changes libGlobal.thoughtManagerObj to the value of the new player character's myThoughtManager property, provided the latter is not nil.
There is no need to do bother with any of this if the player character never changes (if thinker is left undefined on the sole ThoughtManager it will be assumed to belong to the sole player character), and you may prefer not to set up multiple ThoughtManagers for multiple player characters if your Thoughts are intended to model the player's thoughts rather than the player characters'.
Handling the THINK command.
If nothing else intervenes, a bare THINK command results in the output produced by sayDefaultThought(), a method of the Think action object. If you just want THINK to respond with the same message throughout your game, you can simply override sayDefaultThought to display whatever message you like.
If, however, you'd like the reponse to THINK to vary according to circumstances, you can define the Think action object's ruleBook property to point to a RuleBook you define elsewhere in your game to handle your varied responses to THINK. To do this you'll also need to include the rules extension in your project. For example:
modify Think ruleBook = thinkRules ; thinkRules: RuleBook defaultValue = true ; + Rule "You're apprehensive about meeting this sorceress, but it seems to be your best bet --- indeed, your only remaining bet. " where = startroom ; + Rule "It's make up your mind time. You can either head back to the cottage and brave an audience with the mysterious Mirabel or abandon all hope of escaping your life of vagrancy. " where = lane ;
Alternatively, you can define the rulebook you want to use for your THINK reponses to be an object of the ThinkRules class. It will then automatically register itself with the Think action (provided Think.ruleBook
is nil) and its defaultValue property will already be set to true. You could then just define:
ThinkRules ; + Rule "You're apprehensive about meeting this sorceress, but it seems to be your best bet --- indeed, your only remaining bet. " where = startroom ; // etc.