diff --git a/docs/manual/changelog.htm b/docs/manual/changelog.htm index 3c0f84f..25346db 100644 --- a/docs/manual/changelog.htm +++ b/docs/manual/changelog.htm @@ -40,32 +40,32 @@

Change Log


-

Version 2.0 (tbd)

-

POSSIBLE COMPATIBILITY ISSUES: Version 2.0 of adv3Lite should be fully backwards compatible with games written in previous versions APART FROM possible name clashes caused by the introduction of new features involving new identifiers in adv3Lite version 2. Should such clashes occur, you will probably need to change the clashing identifier names in your game.

+

Version 2.0 (03-May-2024)

+

POSSIBLE COMPATIBILITY ISSUES: Version 2.0 of adv3Lite should be fully backwards compatible with games written in previous versions APART FROM possible name clashes caused by the introduction of new features involving new identifiers in adv3Lite version 2. Should such clashes occur, you will need to change the clashing identifier names in your game.

Identifier names that are affected include Fact, FactConsultTopic, FactHelper, FactThought,Mood, Stance and SpecialVerb (now class names in the library) together with some property/names that include words like 'fact', 'mood' and 'stance'. In addition likely, dubious, unlikely and untrue are now enums defined in the library. The various uses of these new identifiers are explained below.


-

Some internal changes have been made to the Actor and Player classes that should not affect existing code. The core module thing.t now defines a very basic class that is replaced by the one in actor.t. This allows the Player class to descend from Actor (which makes more sense in a game where the player character might change). It also removes the potential difficulty of some code in core modules wanting to refer to an Actor class. It is recommended that the Player class be always used to define the player character from now on (especially in new games). +

Some internal changes have been made to the Actor and Player classes that should not affect existing code. The core module thing.t now defines a very basic class that is replaced by the one in actor.t. This allows the Player class to descend from Actor. It also removes the potential difficulty of some code in core modules wanting to refer to an Actor class. It is recommended that the Player class always be used to define the player character from now on (especially in new games).


Library preinitialization now sets the globalParamName of every Actor for which is is not already defined. The globalParamName is set to the name of the Actor object, for example the globalParamName of bob is set to 'bob'. This makes it a little easier for game authors to use a recognizable globalParamName in message parameter substitutions (and for library code to assume this will be available). Existing code should not be affected, since any existing globalParamNames will not be changed.


-

There has been a change to the way the library sets the identity of the initial player character on libGlobal (or rather, the addition of a failsafe way of doing this). libGlobal.playerChar() is now defined as a method which establishes the identity of the initial player character (or creates one if none can be found) and then sets itself to the player character object it finds. This means it is safe to use gPlayerChar even in situations, such as preinit, where it may not have been set yet, since in that case the first call to gPlayerChar (i.e. libGlobal.playerChar() will cause its value to be set.

+

There has been a change to the way the library sets the identity of the initial player character on libGlobal (or rather, the addition of a failsafe way of doing this). libGlobal.playerChar() is now defined as a method which establishes the identity of the initial player character (or creates one if none can be found) and then sets itself to the player character object it finds. This means it is safe to use gPlayerChar even in situations, such as preinit, where it may not have been set yet, since in that case the first call to gPlayerChar (i.e. libGlobal.playerChar() will cause its value to be found and set.

The number of numbered items that can appear in an enumerated disambiguation list has been increased to twenty. This is also the effective cap, since the parser isn't designed to handle a larger number correctly (if the player enters a number higher than 20, the game may respond as if it worked, but the wrong item will be selected).


The Actor method arouse(key, stat) now has a second optional parameter stat, which defaults to true for compatibilty with existing code. If stat it nil, the effect of arouse() is reversed, setting the curiosityAroused property of all ActorTopicEntries matching key to nil. A new conversation tag <.abate key> (or if you prefer <.unarouse key>) can be used to call arouse(key, nil) to reset curiosityAroused to nil on the relevant ActorTopicEntries in the same way. This is for use in situations where the player character's attention has changed to a different topic or set of topic but the PC's curiosity has not been satisfied (because the player might want to return to further topics sharing the same key).


-

A number of enhancements have been made to the triggering of subtopics from a master topic. The new ActorTopicEntry property autoSuppress now controls the listing of suggesed topics when a master TopicEntry triggers a list of subtopics through its keyTopics property; for example where an AskTopic that responds to ASK FRED ABOUT ISLAND has keyTopics of 'island' that in turn causes the game to suggest a number of subtopics (e.g. "What is this island called?", "Where is this island?", "How many people live here?") that the player can then choose between. Setting autoSuppress to true (the default) on the master topic (e.g., AskTopic @tIsland) will suppress the suggestion of the master topic while any of its subtopics (e.g. "Where is this island?") is in the current list of suggestions.

+

A number of enhancements have been made to the triggering of subtopics from a master topic. The new ActorTopicEntry property autoSuppress now controls the listing of suggested topics when a master TopicEntry triggers a list of subtopics through its keyTopics property; for example where an AskTopic that responds to ASK FRED ABOUT ISLAND has keyTopics of 'island' that in turn causes the game to suggest a number of subtopics (e.g. "What is this island called?", "Where is this island?", "How many people live here?") that the player can then choose between. Setting autoSuppress to true (the default) on the master topic (e.g., AskTopic @tIsland) will suppress the suggestion of the master topic while any of its subtopics (e.g. "Where is this island?") is in the current list of suggestions.


-

The ActorTopicEntry class also has a new autoSuppressSubTopics property, which is the complement of the above autoSuppress property. If autoSuppressSubTopics is true (the default) then if a player changes the subject from one master topic to another (e.g. from ASK ABOUT ISLAND to ASK ABOUT WEATHER) then the subtopics suggested by the first master topic (e.g., "Where is this island?") will have their curiositySatisfied property reset to nil, so that they will no longer appear in response to a TOPICS command (unless and until the player types ASK ABOUT ISLAND) again. This is intended to model the player/player character's shift of attention and to declutter the list of suggested topics.

+

The ActorTopicEntry class also has a new autoSuppressSubTopics property, which is the complement of the autoSuppress property. If autoSuppressSubTopics is true (the default) then if a player changes the subject from one master topic to another (e.g. from ASK ABOUT ISLAND to ASK ABOUT WEATHER) then the subtopics suggested by the first master topic (e.g., "Where is this island?") will have their curiosityAroused property reset to nil, so that they will no longer appear in response to a TOPICS command (unless and until the player types ASK ABOUT ISLAND) again. This is intended to model the player/player character's shift of attention and to declutter the list of suggested topics.


-

The ActorTopicEntry class also has a new arouseKeyTopics property. If this is true (the default) there is no need to include <.arouse key> before 'key' in the keyTopics property of an ActorTopicEntry that's designed to suggest a list of subtopics (although doing so will still also work). This means that instead of writing keyTopics = [<.arouse key>, 'key'] you can just write keyTopics = ['key'] (if you want all the topics keyed by key to have curiosityAroused set to true). The new activateKeyTopics (by default nil) works similarly to activate the same subtopics.

+

The ActorTopicEntry class also has a new arouseKeyTopics property. If this is true (the default) there is no need to include <.arouse key> before 'key' in the keyTopics property of an ActorTopicEntry that's designed to suggest a list of subtopics (although doing so will still also work). This means that instead of writing keyTopics = [<.arouse key>, 'key'] you can just write keyTopics = ['key'] (if you want all the topics keyed by key to have curiosityAroused set to true). The new activateKeyTopics (by default nil) works similarly to activate the same subtopics.


-

The ActorTopicEntry class also has a new lastConvResponse property. This is mainly intended for ActorTopicEntries that are mixed in with StopEventList, where the final response in the list is not something said by the actor but the narrator's summary of what the actor said previously. Setting lastConvResponse to -1 (typically) will abbreviate a useful coding pattern that was previously needed to treat the final response as a non-conversational one that did not need to be suggesed.

+

The ActorTopicEntry class also has a new lastConvResponse property. This is mainly intended for ActorTopicEntries that are mixed in with StopEventList, and where the final response in the list is not something said by the actor but the narrator's summary of what the actor said previously. Setting lastConvResponse to -1 will abbreviate a useful coding pattern that was previously needed to treat the final response as a non-conversational one that did not need to be suggested.


-

The TopicGroup class now has a contents property and a curiosityAroused property. The contents property contain a list of all the topic entries located in this TopicGroup. If the curiosityAroused property is not set to -1 (the default) it will be copied to the curiosityAroused property of all the contained topic entries at game startup/preinit. This can be useful in setting up groups of subtopics to be suggested by a master topic.

+

The TopicGroup class now has a contents property and a curiosityAroused property. The contents property contain a list of all the topic entries located in this TopicGroup. If the curiosityAroused property is not set to -1 (the default) it will be copied to the curiosityAroused property of all the contained topic entries at game startup/preinit. This can be useful in setting up groups of subtopics to be suggested by a master topic.


-

A new Scenery class has been added to facilitate the creation of multiple Decorations. Instead of having to create a number of Decoration objects individually, the Scenery class allows you to define a related set of decorations on a single object with minimal typing, for instance the following would be equivalent to five different Decoration objects placed in the forest location: +

A new Scenery class has been added to facilitate the creation of multiple Decorations. Instead of having to create a number of Decoration objects individually, the Scenery class allows you to define a related set of decorations on a single object with rather less typing; for instance the following would be equivalent to five different Decoration objects placed in the forest location:

    Scenery @forest
    [
@@ -78,28 +78,31 @@ 

Version 2.0 (tbd)

The nullObj in the 'twigs' line causes any attempt to refer to the twigs to be responded to with "That's not something you need to refer to. "


-

The Consultable class now has a topicEntryList property which can be used to automate the creation of simple ConsultTopics in a manner analogous to the creation of Decoration objects by the new Scenery class introduced above. +

The Consultable class now has a topicEntryList property which can be used to automate the creation of simple ConsultTopics in a manner analogous to the creation of Decoration objects by the new Scenery class.


-

There is now a SpecialVerb class that can facilitate handling commands that apply to only a handful of objects in a game. For example, if a game has a doorbell that can be rung by being pushed, instead of having to define a new Ring Action and VerbRule(Ring) and dobjFor(Ring) blocks on both Thing and the doorbell object just to handle this one case, you can simply define:

+

There is now a SpecialVerb class that can facilitate handling commands that apply to only a handful of objects in a game. For example, if a game has a doorbell that can be rung by being pushed, instead of having to define a new Ring Action and VerbRule(Ring)) and dobjFor(Ring) blocks on both Thing and the doorbell object just to handle this one case, you can simply define:

SpecialVerb 'ring' 'push' @doorbell;


-

The say() function has been tweaked so that it can now display the names of enums; for example say(small) now outputs 'small'. Internally the enum names are stored in the LookupTable enumTabObj.enumTab in english.t. Some of the string name equivalents of enums are predefined in this table; any that are not at added at preinit. This is to allow translators to provide own-language equivalents of enum names, so that, for example, say(small) might output 'petit' in a French game.

+

The say() function has been tweaked so that it can now display the names of enums; for example say(small) now outputs 'small'. Internally the enum names are stored in the LookupTable enumTabObj.enumTab in english.t. Some of the string name equivalents of enums are predefined in this table; any that are not at added at preinit. This is to allow translators to provide own-language equivalents of enum names, so that, for example, say(small) could be made to output 'petit' in a French game.


There has been some reworking of the knowledge framework, principally to facilitate distingushing player knowledge from player character knowledge where these might diverge (especially when the player character can change in the course of play). As before, anything that have been revealed (typically through gReveal(tag) or <.reveal tag>) is stored in the table of revealed tags on libGlobal, but is now also stored in the informedAboutTab on the current player character. If the player character changes, therefore, the new player character will no longer inherit the old player character's knowledge (as stored in its informedAboutTab) but may start out with a different set of knowledge of its own (encapsulated in its own informedAboutTab).

+

Additionally, the Thing methods setKnowsAbout(obj) and knowsAbout(obj) can now take a inform/reveal string tag as its argument as well an an object. so that setKnowsAbout(tag) has the same effect as setInformed(tag) and knowsAbout(tag) the same effect as informedAbout(tag) when tag is a single-quoted string. The new macro gKnown(tag), which expands to (gPlayerChar.knowsAbout(obj)) can thus be used to test for the player character's knowledge both of objects and of facts encapsulated in string tags (which could conceivably differ from what has been revealed.

The new Thing property initiallyKnowsAbout can used to store a list of objects and tags the Thing in question (usually but not necessarily an actor) starts the game already knowing about.

+

The methods and properties relating to the informed mechanism have been moved from Actor to Thing. This is in part to ensure that they work on the player character object if it has been defined as a Thing, but also to allow it to be used with inanimate objects (such as Consultables) which may also 'know' (be informed about) certain facts, things and topics.

Thing now has a new forget(tag) method that causes the Thing (usually an Actor or Consultable) forget all about having been informed about tag.

-

The behaviour of the CONSULT ABOUT and THINK ABOUT actions have been tweaked to avoid a problem that could arise if they used the <.reveal> tag (or used the reveal mechanism some other way): previously the library called the setInformed method of any actor within hearing distance whenever something was revealed on the basis that they'd overhear the conversational exchange in which it was revealed, but, of course, NPCs shouldn't overhear the player thinking or looking things up. This would only be a problem if the player character thought about or looked things up in the course of a conversation, but since these things could happen these actions now suspend the converational context (by setting the current interlocutor to nil) while the THINK ABOUT and CONSULT ABOUT actions are handled, and then restore the current interluctor (if there was one). This should ensure that bystanders no longer overhear thoughts or whatever the player character looks up in the course of a conversation.

+

The behaviour of the CONSULT ABOUT and THINK ABOUT actions have been tweaked to avoid a problem that could arise if they used the <.reveal> tag (or used the reveal mechanism some other way): previously the library called the setInformed method of any actor within hearing distance whenever something was revealed on the basis that they'd overhear the conversational exchange in which it was revealed, but, of course, NPCs shouldn't overhear the player thinking or looking things up. This would only be a problem if the player character thought about or looked things up in the course of a conversation, but since these things could happen these actions now suspend the converational context (by setting the current interlocutor to nil) while the THINK ABOUT and CONSULT ABOUT actions are handled, and then restore the current interluctor (if there was one). This should ensure that bystanders no longer overhear thoughts or whatever the player character looks up in the course of a conversation.

+

The <.known val> tag can now be used with fact tag names as well as object names provided that val is not a valid object name if it's intended to be a fact tag name. To force a fact tag name that would otherwise be a valid object name to be invalid, you can preface it with a special character (by default, '$') which will then be stripped from the start of val before it's used.

These changes should all be backward compatible with existing game code apart from marginal differences in what gRevealed() and <.reveal> do. The differences may be more apparent on games in which the player character changes in the course of play and which already test for the new player character's knowledge via its informedAboutTab, but the practical impact on most games is likely to be minimal.


As a further refinement to the knowledge model, the Thing function setInformed(tag, arg?) and the libGlobal function setRevealed(tag, arg?) now have an optional second parameter arg. If this is supplied it will stored as the value of the tag key in the associated LookupTable. Both functions can also be used to change the value of an existing entry.

-

The library also now defines a set of enums, likely, dubious, unliklely, and untrue, for possible additional values of this seoond parameter, allowing games to track the level of credence an actor gives a piece of information (with the default value true retained for items accepted as true). As yet the library does nothing with these values (apart from one case in the new Fact Relations - extension), so it will be up to game authors to use --- or not use --- them as they see fit.

+

The library also now defines a set of enums, likely, dubious, unliklely, and untrue, to provide possible values of this seoond parameter, allowing games to track the level of credence an actor gives a piece of information (with the default value true retained for items accepted as true). As yet the library does nothing with these values (apart from one case in the new Fact Relations + extension), so it will be up to game authors to use — or not use — them as they see fit.

These enums can be used in <.reveal> and <.inform> tags by placing an = sign directlty between the tag name and the enum (or other value), e.g. <.reveal troubles=dubious>. For further information, see the new section on Knowledge, Truth and Belief. @@ -107,7 +110,7 @@

Version 2.0 (tbd)


The new (and currenlty experimental) Belief Calculations extension implements various calculations involving the belief enums likely, dubious, unlikely and untrue (together with true) when combined using various operators for AND, OR and NOT (or COMPLEMENT). It does not require the new Facts module, but neither does it provide a particularly realistic simulation of how most people reckon these things. For further details, see the comments in beliefcals.t


-

There is also a new Facts module that extends the adv3Lite knowledge system by allowing game authors to define Fact objects that encapsulate (and help to track and use) the information associated with <.reveal> and <.inform> tags, so for example there can be Fact object called 'rain-tomorrow' that encapsulates what information has been revealed by a <.reveal rain-tomorrow> tag and who knows about it and what game objects or topics it concerns. In this context a Fact is something that has been asserted to be true by some person or object (e.g. book) in the game; not something that is necessarily in fact true.

+

There is also a new Facts module that extends the adv3Lite knowledge system by allowing game authors to define Fact objects that encapsulate (and help to track and use) the information associated with <.reveal> and <.inform> tags, so for example there can be Fact object called 'rain-tomorrow' that encapsulates what information has been revealed by a <.reveal rain-tomorrow> tag and who knows about it and what game objects or topics it concerns. In this context a Fact is something that has been asserted to be true by some person or object (e.g. book) in the game; not something that is necessarily true.


The functionality of the optional Facts module can be further extended by the new Fact Relations extension. This extends the functionality of the Facts module by defining a number of relations involving Facts and using them to enhance the conversational abilities of NPC, for example by enabling NPCs to steer conversations towards desired goals through a chain of related topics.

@@ -119,11 +122,10 @@

Version 2.0 (tbd)

In additional to all these enhancements to the cognitive abilities of NPCs, there are some initial steps to modelling their affective states. Each Actor now has a mood property and a stance property (meaning stance towards the player character, although ambitious game authors can also set and test actor stances towards other actors provided the full adv3Lite library is present). The different possible moods and stances are defined in objects of the Mood and Stance classes. The library definea a number of these but it is very straightforward for game code to define more if desired.


-

The functionality of the DSDoor class has been slightly enhanced (to bring it closer to that of SymDoor) and the standard library now also has DSPassage, DSPathPassage, DSStairway and DSTravelConnector classes to allow passages and stairways to be defined as single objects instead of pairs of objects. In addition to bringing the convenioence of these classes to the standard library, this more clearly separates the provision of double-sided (aka two-way) travel connector objects from the original function of the SymConn extenstion, which is to automate the setting up of reciprocal map connections.

-

In turn the SymConn extension has been radically refacrtored to leverage the new DSCOn classes in the main library. It should still, however, work in exactly the same way as before from the perspective of game authors, except that as the underlying class inheritance hierarchy has changed, modifying classes higher up in that hierarchy may conceivably have different effects from before (e.g., SymDoor now inherits from Door, via DSDoor, so a modification to Door would now affect SymDoor, which it would not have done previously).

+

The functionality of the DSDoor class has been slightly enhanced (to bring it closer to that of SymDoor) and the standard library now also has DSPassage, DSPathPassage, DSStairway and DSTravelConnector classes to allow passages and stairways to be defined as single objects instead of pairs of objects. In addition to bringing the convenience of these classes to the standard library, this more clearly separates the provision of double-sided (aka two-way) travel connector objects from the original function of the SymConn extenstion, which is to automate the setting up of reciprocal map connections.

+

In turn the SymConn extension has been radically refactored to leverage the new DSCon classes in the main library. It should still, however, work in exactly the same way as before from the perspective of game authors, except that as the underlying class inheritance hierarchy has changed, modifying classes higher up in that hierarchy may conceivably have different effects from before (e.g., SymDoor now inherits from Door, via DSDoor, so a modification to Door would now affect SymDoor, which it would not have done previously).


-

There is now a maxItemsCarried capacity that defines the maximum number of items an actor can carry regardless of their bulk (or weight). This is checked in addition to the bulk the actor is carrying. This allows game authors to limit the number of items an actor (especially the player character) can carry in addition to the maximum bulk they can carry. The default value of maxItemsCarried is very large (100,000) so this unlikely to be a limit ever reached unless the game author overrides it to a lower value. If the player character is holding an appropriate BagOfHolding, the game will attempt to move carried items to it if either the bulkCapacity or the maxItemsCarried is exceeded.


@@ -138,7 +140,7 @@

Version 2.0 (tbd)

The AgendaItem class now has new endCondition and executeOnce properties that can (opitionally) be used to control when its isDone property becomes true. If executeOnce is true, then isDone will be set to true after the first invocation of invokeItem(), while endCondition can be defined as a method or expression that is checked both immediately before and immediately after invokeItem() is called and sets isDone to true if endCondition evaluates to true.


-

There is also a new gActorRoom macro that expands to (gActor.getOutermostRoom). +

There is now a new gActorRoom macro that expands to (gActor.getOutermostRoom).


The library now defines a pair of new templates for the CommandTopic class to facilitate defining their matchDobj and matchIobj properties.


@@ -151,7 +153,7 @@

Version 2.0 (tbd)

There have been some tweaks to the DerivedRelation class in the Relations extension designed to make it easier to use and debug.


-

Some of the longer methods on TravelAction have been broken down into smaller ones to make it easier for user code to customize the handling of travel (I recall seeing this being desired a while back on intfiction.org). This should not result in any changes to the way the library handles travel.

+

Some of the longer methods on TravelAction have been broken down into smaller ones to make it easier for user code to customize the handling of travel (I recall seeing this being requested a while back on intfiction.org). This should not result in any changes to the way the library handles travel.


There has been a minor reorganization of library variants. What used to be called adv3Liter is now called adv3Litest, while the name adv3Liter is now applied to a library variant included all the core modules plus many (but not all) of the optional ones, to give a usable, but truly 'liter' version of the library comparable in power to Inform 6 or TADS 2 with a few extra features. For a fuller explanation see the new section on Options and Alternative Libraries — Lite, Liter and Litest.


diff --git a/extensions/beliefcalcs.t b/extensions/beliefcalcs.t index f3cb1e3..bdae602 100644 --- a/extensions/beliefcalcs.t +++ b/extensions/beliefcalcs.t @@ -23,6 +23,9 @@ *. BV(a) & BV(b) the belief enum for a and b *. BV(a) + BV(b) the probability (as a number out of 100) of a and b. *. ~BV(a) the negation/complement of a, e.g. ~BV(likely) = unlikely + *. BV(a) >> BV(b) test whether a.score > b.score + *. BV(a) << BV(b) test whether a.score < b.score + *. BV(a) >>> BV(b) test whether a.score >= b.score * * One major limiation of this extension is that it does not repreaent how most people reason * about probabilities in practice. A second, related, limitation is that the probabilities @@ -229,7 +232,9 @@ class BelVal: object operator * (x) { return (self.score * x.score) / 100; } operator ~ () { return intToVal(100 - self.score); } operator + (x) { return 100 - ((100 - score) * (100 - x.score)) /100 ; } - + operator >> (x) { return self.score > x.score; } + operator << (x) { return self.score < x.score; } + operator >>> (x) { return self.score >= x.score; } /* Convert a number (a probability from 0 to 100) into a belief enum. */ intToVal(num) diff --git a/extensions/docs/factrelation.htm b/extensions/docs/factrelation.htm index 5bd68e0..ce55004 100644 --- a/extensions/docs/factrelation.htm +++ b/extensions/docs/factrelation.htm @@ -580,11 +580,61 @@

FactAgendaItem

Note that the reset() method could allow us to use a single FactAgendaItem per actor to cater for all that actor's fact-based conversational agendas. It could also be used to change the actor's conversational target in mid-conversation, before the original goal had been reached.

Note also the comment in the example above about wrapping the first response to asking about the weather in an anonymous function. If we had simply used a single-quoted string here ('<q>\^<<revTag()>></q> Bob warns you. ') it would have displayed what we wanted but there would have been a subtle unwanted side-effect. Because of the way TADS 3 handles lists, every single-quoted string in an EventList is evaluated every time the EventList is referenced, regardless of which element of the EventList we actually want. So had we used a single-quoted string, revTag() would have been called again even on the second or subsequent invocation of this TopicEntry. Because revTag() not only displays the desc of the associated fact but reveals the associated fact tag, this would cause libGlobal.lastFactMentioned to revert to 'rain-tomorrow', which in turn would set bobAgenda's starting fact to 'rain-tomorrow', with the result that Bob would repeat his remark about the rain in Spain, which is precisely what we were trying to avoid by calling fText() rather than revTag() second time around.

-
+

Using Topic Entries with FactAgendaItems

+ +

Finally, the Fact Relation extension adds a couple of features to ActorTopicEntry to work with FactAgendaItem in case the player enters a conversational command concerning a topic that is or maybe related to a Fact on the conversational path a FactAgendaItem is trying to follow. In that case we might want the FactAgendaItem to provide the response, rather than have our TopicEntry provide one that may not be so appropriate in context.

+

Suppose, for example, we had defined the following AskTopic:

+ +

 
+++ AskTopic @mavis
+    "How is Mavis? you ask. \b
+    <She's fine, Bob tells you."    
+;
+ 
+

This might be a perfectly sensible response to give once Bob has revealed his plan to propose to Mavis, and we may feel that some such response ought to be provided, but since Bob is meant to be bursting to tell our player character about his planned proposal, one might expect him to cut straight to the chase. We could, of course, try to rectify the situation by adding a suitable isActive property to our AskTopic:

+ + +

 
+++ AskTopic @mavis
+    "<q>How is Mavis?</q> you ask. \b
+    <<q>She's fine,</q> Bob tells you."
+	
+    isActive = !gRevealed('mavis-proposal')
+;
+ 
+ +

But this would then rob the player character of his ability to ask how Mavis is until Bob has revealed his proposal plan. What we might ideally like is for our AskTopic to advance along our FactAgendaItem's path towards the Mavis proposal if it has not yet reached its goal, but provide the "She's fine" response otherwise. We can do this with:

+ + +

 
+++ AskTopic @mavis
+    "<q>How is Mavis?</q> you ask. \b
+    <<unless tryAgenda()>><q>She's fine,</q> Bob tells you. <<end>>"    
+    
+    autoName = true    
+   
+    autoUseAgenda = true    
+;
+
+ 
+

This then gives us the best of both worlds: our AskTopic will see if a suitable FactAgendaItem can provide a suitable reply about Mavis and display it if so; otherwise it uses the "She's fine" response.

+ + +

The relevant new properties/methods of ActorTopicEntry that enable us to do this are:

+ + + - +

This covers most of what you need to know to use this extension. For additional information see the source code and comments in the factrel.t file.

diff --git a/extensions/factrel.t b/extensions/factrel.t index 81da003..418d182 100644 --- a/extensions/factrel.t +++ b/extensions/factrel.t @@ -554,6 +554,7 @@ modify ActorTopicEntry */ autoUseAgenda = nil + /* Look for an appropriate FactAgendaItem to use with this TopicEntry. */ useAgenda() { /* Don't do anything here if we don't want to reference an associated FactAgendaItem */ @@ -597,6 +598,7 @@ modify ActorTopicEntry } finally { + /* Restore the previous last fact mentioned. */ libGlobal.lastFactMentioned = formerFact; } @@ -604,7 +606,13 @@ modify ActorTopicEntry baseHandleTopic() { + /* + * Set up a variable to hold the AgendaItem we want to work with and initialize it to the + * value of our agenda property, so we cab restore it to its original value when we're + * done. + */ local agenda_ = agenda; + try { if(agenda || autoUseAgenda) @@ -621,8 +629,10 @@ modify ActorTopicEntry */ agendaPath = ag.getPath(); + /* Cache our agenda item's nextSteo in our own nextStept property. */ nextStep = ag.nextStep; + /* Store the agenda we've found in our agenda property. */ agenda = ag; } else @@ -630,14 +640,17 @@ modify ActorTopicEntry /* Otherwise reset our nextStep and agendaPath to nil */ nextStep = nil; + /* Reset our agendaPath property to nil. */ agendaPath = nil; } } + /* Carry out the inherited handling. */ inherited(); } finally { + /* Restore the original value of our agenda property. */ agenda = agenda_; } } @@ -655,22 +668,40 @@ modify ActorTopicEntry */ agendaPath = nil + /* + * A method our topicResponse property can call to try executing the next step of our + * associated agenda item to provide a response. This returns true if there is a nextStep to + * execute or nil otherwise so our topicResponse can test whether tryNextStep() has provided a + * response. + */ tryNextStep() { + /* + * If we have a next step, call our getActor's initiateTopic with nextStep as its argument + * abd see if it provides a response. + */ if(nextStep) { + /* + * If calling initiateTopic(nextStep) on our actor provides a response, return true to + * tell our caller that we've done so. + */ if(getActor.initiateTopic(nextStep)) return true; } + /* Otherwise we haven't provided a response, so return nil to tell our caller we haven't. */ return nil; } + /* + * tryAgenda is an alternative method our topicResponse can call; it simply executes our + * associated AgendaItem and returns true or nil to our caller so it can tell whether this + * provided a response. + */ tryAgenda() { return getActor.executeAgenda(); - } - - + } ; /* Modifications to AltTopic to work with FACT RELATIONS modifications to ActorTopicEntry */ diff --git a/readme.htm b/readme.htm index ffcc2f6..e43a4a6 100644 --- a/readme.htm +++ b/readme.htm @@ -7,7 +7,7 @@
-

ADV3LITE VERSION 1.6.2

+

ADV3LITE VERSION 2.0

Thank you for your interest in adv3Lite, an alternative library for use with the TADS 3 Interactive Fiction authoring system.