Skip to content

Instantly share code, notes, and snippets.

@realnc
Last active December 7, 2016 08:38
Show Gist options
  • Save realnc/9bdaeb6b1fbc0aaa50b065ef64942dbc to your computer and use it in GitHub Desktop.
Save realnc/9bdaeb6b1fbc0aaa50b065ef64942dbc to your computer and use it in GitHub Desktop.
TADS 3 module for yes/no answers to the narrator.
#charset "UTF-8"
/*
* Module for yes/no answers to the narrator.
* 2003/06/17, by Nikos Chantziaras <realnc@gmail.com>
* This file is in the Public Domain. There is no copyright.
*
* To use this module, simply compile it together with the rest of your
* game's source files.
*/
#include <adv3.h>
#include <en_us.h>
/*
* To enable the player to answer a question asked by the narrator (NPC
* questions are handled by the Tads 3 library), call one of the "set"
* methods of the ncYesNo object. The methods are:
*
* set( STRING_OR_FUNCTION, STRING_OR_FUNCTION )
*
* The arguments must be either strings or functions that take no
* arguments. The first argument is called/displayed when the player
* types YES, the second when the answer is NO. Example:
*
* dobjFor(Attack)
* {
* action()
* {
* "Attacking the troll is pretty dangerous. Are you sure? ";
* ncYesNo.set(
* // This anonymous function will be called if the player
* // anwers with YES.
* {:
* "You get ready for battle, but the troll kills you
* before you can even blink!\b*** You have died ***\b";
* finishGame(finishOptionUndo);
* },
* // This string will be displayed if the player anwers NO.
* 'Wise decision. '
* );
* }
* }
*
* setAll( STRING_OR_FUNCTION )
*
* Same as set(), but the argument is used for both YES and NO.
*
* setRhetorical()
*
* This calls setAll() like this:
*
* self.setAll(self.rhetoricalAnswer);
*
* The property 'rhetoricalAnswer' contains the string to be displayed
* with setRhetorical(). The default is: 'That was a rhetorical
* question. ' If you want to display something else, you can simply
* set it to something different:
*
* modify ncYesNo {
* rhetoricalAnswer = 'The question was rhetorical. ';
* }
*
* The property 'defaultYesAnswer' contains the string to be displayed
* when the player types YES while no question has been asked and the
* PC has no current interlocutor. The default is: 'You sound rather
* positive. '
*
* Similarly, the 'defaultNoAnswer' property defaults to: 'You sound
* rather negative. '
*
* The player has only one turn to answer to a question. After that,
* the reset() method is called, which resets any effects caused by one
* of the "set" methods.
*
* The situation where the PC has a current interlocutor is handled
* automaticly. Example:
*
* >no
* I'm glad you disagree.
*
* >bob, no
* Bob does not respond.
* [The PC's current interlocutor is now Bob.]
*
* >no
* Bob does not respond.
*
* >knock on my door
* Don't you think knocking on your own door is a bit strange?
*
* >no
* That was a rhetorical question.
* [Although the current interlocutor is Bob, we treat NO as the
* answer to the narrator's question.]
*
* >no
* Bob does not respond.
* [Since the player already answered the narrator's question, NO is
* now redirected to Bob.]
*/
ncYesNo: object {
rhetoricalAnswer = 'That was a rhetorical question. ';
defaultYesAnswer = 'You sound rather positive. ';
defaultNoAnswer = 'You sound rather negative. ';
reset()
{
if (self._active) {
self._onYes = nil;
self._onNo = nil;
self._active = nil;
self._myFuse.removeEvent();
self._myFuse = nil;
if (self._lastIssuer.isPlayerChar()) {
self._lastIssuer.lastInterlocutor = self._lastInterlocutor;
}
}
}
set( yes, no )
{
if (self._active) self.reset();
self._onYes = yes;
self._onNo = no;
self._active = true;
self._myFuse = new Fuse(self, &reset, 1);
self._lastIssuer = gIssuingActor;
self._lastInterlocutor = self._lastIssuer.getCurrentInterlocutor();
}
setAll( yesOrNo )
{
self.set(yesOrNo, yesOrNo);
}
setRhetorical()
{
self.setAll(self.rhetoricalAnswer);
}
// Private members; do not modify or evaluate.
_onYes = nil;
_onNo = nil;
_active = nil;
_myFuse = nil;
_lastIssuer = nil;
_lastInterlocutor = nil;
}
/* --------------------------------------------------------------------
* Modify YesAction and NoAction to use the ncYesNo system.
*/
modify YesAction {
execAction()
{
if (gActor.isPlayerChar()) {
if (ncYesNo._active) {
if (dataType(ncYesNo._onYes) == TypeSString) {
say(ncYesNo._onYes);
} else {
(ncYesNo._onYes)();
}
} else {
if (gIssuingActor.getCurrentInterlocutor()) {
inherited();
} else {
say(ncYesNo.defaultYesAnswer);
}
}
} else {
inherited();
}
}
}
modify NoAction {
execAction()
{
if (gActor.isPlayerChar()) {
if (ncYesNo._active) {
if (dataType(ncYesNo._onNo) == TypeSString) {
say(ncYesNo._onNo);
} else {
(ncYesNo._onNo)();
}
} else {
if (gIssuingActor.getCurrentInterlocutor()) {
inherited();
} else {
say(ncYesNo.defaultNoAnswer);
}
}
} else {
inherited();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment