Version 1 of Quip-Based Conversation SP by Michael Martin begins here.

"An extension to allow traditional conversation menus, in the vein of Inform 6's phtalkoo.h extension.  Requires Reactable Quips."

Include Version 3 of Reactable Quips SP by Michael Martin.

[Version 1: Initial release.  We require at least version 3 of RQ because we rely on the conditional Understand commands to handle overrides.]

Section 1 - Cancelling ASK, TELL, and ORDERS

Before asking someone about: clue talking instead.
Before telling someone about: clue talking instead.
Before answering someone that: clue talking instead.
Before asking someone to try doing something: clue talking instead.

To clue talking:
  say "[bracket]Utiliza HABLA CON para interactuar con los personajes.[close bracket][paragraph break]".

Section 2 - Member fields and default values

A person has a quip called a greeting.  The greeting of a person is usually quip_null.
A person has a table-name called the litany.  The litany of a person is usually the Table of No Conversation.  

[This is the currently active litany.]
The qbc_litany is a table-name that varies.  The qbc_litany is the Table of No Conversation.

Table of No Conversation
prompt	response	enabled
a text	a quip		a number

Section 3 - Initiating conversations

Talking to is an action applying to one visible thing.  Understand "habla con [something]" as talking to.

Check talking to: 
  if the noun provides the property litany and the noun provides the property greeting then do nothing; otherwise say "En general, mejor hablar con cosas vivas." instead.

Check talking to:
  if the greeting of the noun is quip_null and the number of enabled rows in the litany of the noun is zero, say "No se te ocurre que decir." instead.

Carry out talking to:
  if the greeting of the noun is not quip_null, deliver the greeting of the noun quip;
  if the number of filled rows in the litany of the noun is not zero begin;
    change the qbc_litany to the litany of the noun;
    display the QBC options;
  end if.

[This is for when we have a Reactable Quips-style followup in the middle of a conversation.]
After responding with (this is the revert to normal conversation rule):
  display the QBC options.

To display the QBC options:
  if the game is over, stop;
  if the pertinent quip is not quip_null, stop;
  let qbc_index be 0;
  repeat through qbc_litany begin;
    if the enabled entry is 1 begin;
      increase qbc_index by 1;
      say "[bracket][qbc_index][close bracket] [prompt entry][line break]";
    end if;
  end repeat;
  if qbc_index is not 0, change the number understood to 0;
  otherwise terminate the conversation.

To decide which number is the number of enabled rows in (t - a table-name):
  let qbc_index be 0;
  repeat through t begin;
    if the enabled entry is 1, increase qbc_index by 1;
  end repeat;
  decide on qbc_index.

Does the player mean talking to a person: it is likely.

Section 4 - Delivering lines

[RQ's reaction code overrides this when necessary.]
QBC responding with is an action applying to one number.  Understand "[number]" as QBC responding with.

Carry out QBC responding with (this is the perform talking rule):
  if the pertinent quip is not quip_null begin;
    say "initiating; pertinent quip is now [the pertinent quip]";
    try responding with the number understood;
    say "completed; pertinent quip is now [the pertinent quip]";
    display the QBC options;
  otherwise if the number of filled rows in the qbc_litany is zero;
    say "[bracket]Ahora no estás en ninguna conversación.[close bracket][line break]";
  otherwise;
    let qbc_index be 0;
    repeat through the qbc_litany begin;
      if the enabled entry is 1 begin;
        increase qbc_index by 1;
        if qbc_index is the number understood begin;
            change the enabled entry to 0;
            deliver the response entry quip;
            display the QBC options;
            rule succeeds;
        end if;
      end if;
    end repeat;
    say "[bracket]Las respuestas válidas son de 1 a [qbc_index].  Teclea REPETIR para ver la lista de opciones.[close bracket][paragraph break]";
  end if.

Section 5 - Recaps

[RQ's recap code overrides this when necessary.]
QBC recap is an action out of world applying to nothing.  Understand "repeat" or "recap" as QBC recap.

Carry out QBC recap (this is the perform QBC recap rule):
  let qbc_index be 0;
  repeat through qbc_litany begin;
    if the enabled entry is 1 begin;
      increase qbc_index by 1;
      if qbc_index is 1, say "Las opciones disponibles son:[paragraph break]";
      say "[bracket][qbc_index][close bracket] [prompt entry][line break]";
    end if;
  end repeat;
  if qbc_index is 0, say "[bracket]Ahora no estás en ninguna conversación.[close bracket][paragraph break]";

Section 6 - Utility functions

To enable the (q - a quip) quip for (o - a thing):
  repeat through the litany of o begin;
    if the response entry is q, change the enabled entry to 1;
  end repeat. 

To disable the (q - a quip) quip for (o - a thing):
  repeat through the litany of o begin;
    if the response entry is q, change the enabled entry to 0;
  end repeat. 

To enable the (q - a quip) quip:
  repeat through the qbc_litany begin;
    if the response entry is q, change the enabled entry to 1;
  end repeat. 

To disable the (q - a quip) quip:
  repeat through the qbc_litany begin;
    if the response entry is q, change the enabled entry to 0;
  end repeat. 

To shift the conversation to (t - a table-name):
  change the qbc_litany to t.

To run a conversation on (t - a table-name):
  shift the conversation to t;
  display the QBC options.

To terminate the conversation:
  change the qbc_litany to the Table of No Conversation.

Quip-Based Conversation SP ends here.

---- DOCUMENTATION ----

Quip-Based Conversation builds upon the Reactable Quips extension to provide a table-driven conversation system for NPCs that smoothly handles Photopia or LucasArts-style conversation menus.  The player character may initiate conversation with a >TALK TO NPC command.  After an optional greeting exchange, the player selects dialogue from a menu.  Options may become available or unavailable as a result of these statements.  The basic functionality of Reactable Quips is retained; NPCs may occasionally say or do things that demand or imply some kind of reaction from the PC, at which point the player must then choose some option off a new menu to characterize the reaction.  After the reaction is selected, the traditional menus return.

The most fundamental concept remains the "quip", which behaves identically to its behavior in Reactable Quips.  Quips are values, not things; they are used to index into the quip tables.

Thus, the one task we must always perform is filling in the Table of Quip Texts.  A default table is provided by the extension, so you will need to continue the table in your own code:

	Table of Quip Texts (continued)
	quip	quiptext
	greeting	"'Why, hello there!'"
	discuss weather	"'Looks like rain, or my name isn't George Washington.'"
	standoff	"'What's it to you, Mac?'"
	silence	"You decide to remain silent for the moment."

People have a "greeting" which is a quip that is delivered when you TALK TO them.  This defaults to the internal value "quip_null" which will result in no greeting and all, moving straight to options.

People also have a "litany" which is a table that holds their actual conversational options.  This defaults to the Table of No Conversation, in which no options are presented at all.  Other litanies have three columns: "prompt" - a string indicating the player's prospective line of dialogue; "response" - a quip that is the NPC's reply; and "enabled", a number that should be 1 if the line is available the first time the character is spoken to, and 0 otherwise.

	George is a man in the Cherry Orchard.  The greeting of George is greeting.  The litany of George is the Table of George Conversation.

	Table of George Conversation
	prompt	response	enabled
	"How's the weather look?"	discuss weather	1
	"How're your teeth doing?"	standoff	1
	"Say nothing"	silence	1

If neither the greeting nor the litany is defined, attempting to talk to the character results in a generic refusal.

Rules may be attached to quips as usual; see the Reactable Quips documentation for how this works in detail.  Briefly, we use rulebooks associated with the quipping activity, and refer to the variable "the current quip" to determine which ones are in use.

A wide variety of phrases are available for use in these rules; most relevant are "enable the X quip" and "disable the X quip", where X is the name of the response quip you wish to make available in the current litany.  If you wish to enable or disable quips in other litanies, you may "enable/disable the X quip for Y" where Y is the name of the person in whose litany you wish to modify the option.  To modify or eliminate the default conversation characteristics of a character, the greeting or litany may be changed normally with commands like "change the litany of X to Y" -- however, changing the litany of a character will not modify the current conversation.  To modify that, you instead "shift the conversation to X".  To run a conversation without an attached person, you may "run a conversation on X".  This will not deliver a greeting quip.  Finally, when talking is done, one may "terminate the conversation".  This is an appropriate reaction to good-bye or say-nothing quips, depending on how they are handled.

Quips disable themselves by default when used.  For permanent quips (such as "say nothing", above), we must re-enable them by hand:

	After quipping when the current quip is silence: enable the silence quip; terminate the conversation.

If "silence" is shared across NPCs, this one rule will work for all of them.  For custom farewell quips, individual rules will be used.

Quips in a litany may have followups defined as per Reactable Quips; see the Reactable Quips documentation for details on how this works.  Note that while Reactions require a response from the player, ordinary conversation does not.  This is a departure from the Phototalk model, but tracks more modern works such as City of Secrets or Beyond.  If you wish to require conversation to continue until stopped, include the following code in your project.

	Instead of doing something other than requesting a recap, responding with, QBC responding with or QBC recap when the qbc_litany is not the Table of No Conversation (this is the QBC force conversation rule):
   say "[bracket]I need some kind of reaction from you to continue the scene.  Enter a number, or say REPEAT to reacquaint yourself with your options.[close bracket][paragraph break]" instead.

	The QBC force conversation rule is listed first in the before rules.

This code may change across versions of Quip-Based Conversations, so if you upgrade mid-project, check this section again.  Also, make sure that all conversations have some option that that both re-enables itself and terminates the conversation, or players will get stuck!

If you keep the default, interruptible conversations, you will need to ensure that conversations terminate when the PC and the NPC being spoken to are no longer in the same location.  If NPCs do not move, a simple

	Before going: terminate the conversation.

will suffice; terminating a conversation that is not in progress is harmless.

Example: *** Joe Schmoe Revisited - A reimplementation of David Glasser's PHTALKOO.H example, with additions showing interaction with Reactable Quips and independent conversations.

Note that in some versions of Inform 7, this code may not work if you simply cut and paste it out of the Documentation window; the tables will not render properly in the Source window.  Copy it out of the actual Documentation file instead.

	"Joe Schmoe Revisited"

	The story headline is "An Interactive Revisiting of the phtalkoo.h Test".
	Include Quip-Based Conversation by Michael Martin.
	Use no scoring.

	Chapter 1 - The Setup

	When play begins, say "Joe Schmoe is yor frend!"

	Joe Schmoe's Place is a room.  "You are in Joe Schmoe's place."

	Joe Schmoe is a man in Joe Schmoe's Place.  The description is "This is Joe. It's yor frend!"  The litany of Joe Schmoe is the Table of Joe Comments.

	The greeting of yourself is selftalk.

	Casting Xyzzy is an action applying to nothing.  Understand "xyzzy" as casting xyzzy.  Carry out casting xyzzy: deliver the xyzzy quip; run a conversation on the Table of Magic Followups.

	Chapter 2 - The Script

	Section 1 - The Text

	Table of Quip Texts (continued)
	quip		quiptext
	selftalk		"Talking to yourself is not particularly fun."
	who-am-i	"'My name is Joe Schmoe and Inform hates me.'"
	why-hate	"'I tried to compile a game and it gave me 40 Problem messages.'"
	yay-inform	"'Thanks so much! You're the greatest!'"
	hate-you	"'I hate you!'[paragraph break] Joe kills you."
	hate-you-2	"'I hate you!'[paragraph break] Joe kills you."
	hate-you-3	"'I hate you!'[paragraph break] Joe kills you."
	hate-pedants	"'I hate pedants!'[paragraph break] Joe kills you."
	yay-monkeys	"'Of course I like monkeys.'"
	yay-you		"'Now we can be friends!'"
	say-nothing	"You decide not to say anything after all."
	ehn-apes	"'Apes are OK, I guess.'"
	ehn-lemurs	"'I don't really have an opinion on lemurs.'"
	xyzzy		"What's the other magic word?"

	Table of Joe Comments
	prompt					response	enabled
	"Who are you?"				who-am-i	1
	"Why does Inform hate you?"		why-hate	0
	"You probably just left out a semi-colon."	yay-inform	0
	"I don't care."				hate-you	0
	"Ha, ha. Inform hates you."		hate-you-2	0
	"Do you like a monkey?"			yay-monkeys	1
	"Only crazy people like monkeys."		hate-you-3	0
	"No, I said 'a monkey', not 'monkeys'."	hate-pedants	0
	"I like monkeys too."			yay-you		0
	"Say nothing"				say-nothing	1

	Table of Quip Followups (continued)
	quip		option			result
	yay-monkeys	"What about apes?"	ehn-apes
	yay-monkeys	"What about lemurs?"	ehn-lemurs

	Table of Magic Followups
	prompt					response	enabled
	"PLUGH"					yay-you		1
	"There are at least two; which one?"	hate-pedants	1

	Section 2 - Dialogue affects itself

	After quipping when the current quip is who-am-i:
	  enable the why-hate quip;
	  enable the hate-you quip.

	After quipping when the current quip is why-hate:
	  disable the hate-you quip;
	  enable the hate-you-2 quip;
	  enable the yay-inform quip.

	After quipping when the current quip is yay-monkeys:
	  enable the hate-you-3 quip;
	  enable the hate-pedants quip;
	  enable the yay-you quip.

	After quipping when the current quip is say-nothing:
	  enable the say-nothing quip;
	  terminate the conversation.

	Section 3 - Dialogue affects the game

	After quipping when the current quip is hate-you: end the game in death.
	After quipping when the current quip is hate-you-2: end the game in death.
	After quipping when the current quip is hate-you-3: end the game in death.
	After quipping when the current quip is hate-pedants: end the game in death.
	After quipping when the current quip is yay-inform: end the game in victory.
	After quipping when the current quip is yay-you: end the game in victory.

	Section 4 - Tests

	test me with "talk to me / x joe / talk to joe / 1 / x me / 1 / repeat / 3 / x me / 1 / 1".
	test xyzzy with "xyzzy / 1".