#charset "us-ascii" #include #include "advlite.h" /* * revision of show() method of suggestedTopicsLister object defined in * actor.t, to allow reordering of topics in the output. Define order in * datastore.topics order. */ replace suggestedTopicLister: object /* Introduce the topic inventory listing */ showListPrefix(lst, pl, explicit) { #ifdef __DEBUG if(dataStore.topicOrder.length != dataStore.adv3LiteDefaultTopicOrder.length) say('<.p>WARNING!!! dataStore.topicsOrder[] list has incorrect number of elements. <.p>'); #endif /* * Introduce the list. If it wasn't explicitly requested start by * outputting a paragraph break and an opening parenthesis. */ if(!explicit) "<.p>("; /* * Then introduce the list of suggestions with the appropriate form of * 'You could' (suitably adjusted for the person of the player * character) */ DMsg(suggestion list intro, '{I} could '); } /* End the list with a closing parenthesis or full stop as appropriate */ showListSuffix(lst, pl, explicit) { /* * Finish the list. If it was explicitly requested we finish it with a * full stop and a newline, otherwise we finish it with a closing * parenthesis and a newline. */ if(explicit) ".\n"; else ")\n"; } /* The message to display if there are no topics to suggest. */ showListEmpty(explicit) { if(explicit) DMsg(nothing in mind, '{I} {have} nothing in mind to discuss with {1} just {then}. ', gPlayerChar.currentInterlocutor.theObjName); } show(lst, explicit = true) { /* * first exclude all items that don't have a name property, since * there won't be anything to show. */ lst = lst.subset({x: x.name != nil && x.name.length > 0}); /* * if the list is empty there's nothing for us to say, so say so and * finish */ if(lst.length == 0) { showListEmpty(explicit); return; } /* * Next we need to divide the list according to category * * * * First we go through the list of suggestion types assigning each * topic entry to the user specified type where the user has specified * that it should be suggested at a specific type of Topic Entry (as * opposed to the library default). */ foreach(local cur in typeInfo) { /* * For each item in our typeInfo list (for which see below), * extract that subset of topic entries from our main list for * which the suggestAs property matches the suggestAs property in * cur (which is the third element of cur). Set the corresponding * list on this lister object (for which we obtain a property * pointer from the first element of cur) to be that subset. */ self.(cur[1]) = lst.subset({t: t.suggestAs == cur[3]}); /* * Then remove the subset we've just identified from the list of * topic entries to be processed, since we've just accounted for * them */ lst -= self.(cur[1]); } /* * Then go through every remaining item in our main list, assigning it * to a sublist on the basis of which type of topic entry it is, which * we'll determine on the basis of the property pointers in its * includeInList. */ foreach(local cur in typeInfo) { /* * For each entry in our typeInfo list, find that subset of our * list of topic entries that corresponds to the typeInfo. A topic * entry will correspond to the cur typeInfo if the second element * of cur (a property pointer such as &askTopics) can be found in * the includeInList of the topic entry, which we can test with * our includes method (defined below). Add the subset thus * created to the list contained in the property defined by the * property pointer held in the first element of cur (e.g. * &sayList), which will be a property of this lister object. */ self.(cur[1]) += lst.subset({t: includes(t, cur[2])}); /* * Remove the sublist we've just created from our overall list of * topic entries, since it's now accounted for. */ lst -= self.(cur[1]); } /* * Introduce the list. */ showListPrefix(lst, nil, explicit); /* Note that we haven't listed any items yet */ local listStarted = nil; /* * Note that the actor we're listing suggestions for is the player * character's current interlocutor. */ local interlocutor = gPlayerChar.currentInterlocutor; /* Create a message parameter substitution for the interlocutor */ gMessageParams(interlocutor); /* * We then output our list of suggestions category by category * * We start with suggested SayTopics, if there are any to display. */ /* * * JF mods begin here---instead of starting with Say topics, use order * defined in dataStore.topicsOrder (for adv3Lite library's default * order, set topicsOrder list to 'say', 'query', 'ask', 'tell', * 'talk', 'give', 'show to', 'ask for', 'yes', 'no' and 'command') * */ local num = dataStore.topicOrder.length; local idx = 1; while(idx <= num) { switch(dataStore.topicOrder[idx++]) { case 'give': if(giveList.length > 0) { if(listStarted) say(orListSep); DMsg(give, 'give {him interlocutor} '); /* Show the list of suggested GiveTopics */ showList(giveList); /* Note that we have now started listing topics */ listStarted = true; } break; case 'tell': if(tellList.length > 0) { /* * If we've already listed some suggestions, output a list * separator before starting the next group. */ if(listStarted) say(orListSep); /* Output an introduction to our list of AskTopics */ DMsg(tell about, 'tell {him interlocutor} about '); /* Show the list of suggested TellTopics */ showList(tellList); /* Note that we have now started listing topics */ listStarted = true; } break; case 'ask': if(askList.length > 0) { /* * If we've already listed some suggestions, output a list * separator before starting the next group. */ if(listStarted) say(orListSep); /* Output an introduction to our list of AskTopics */ DMsg(ask about, 'ask {him interlocutor} about '); /* Show the list of suggested AskTopics */ showList(askList); /* Note that we have now started listing topics */ listStarted = true; } break; case 'query': if(queryList.length > 0) { /* * If we've already listed some suggestions, output a list * separator before starting the next group. */ if(listStarted) say(orListSep); /* Output an introduction to our list of QueryTopics */ DMsg(ask query, 'ask {him interlocutor} '); /* Show the list of suggested QueryTopics */ showList(queryList); /* Note that we have now started listing topics */ listStarted = true; } break; case 'say': if(sayList.length > 0) { /* * If we've already listed some suggestions, output a list * separator before starting the next group. */ if(listStarted) say(orListSep); /* List our suggested SayTopics */ showList(sayList); /* Note that we have now started listing topics */ listStarted = true; } break; case 'talk': if(talkList.length > 0) { /* * If we've already listed some suggestions, output a list * separator before starting the next group. */ if(listStarted) say(orListSep); /* Output an introduction to our list of TalkTopics */ DMsg(talk about, 'talk about '); /* Show the list of suggested TalkTopics */ showList(talkList); /* Note that we have now started listing topics */ listStarted = true; } break; case 'show to': if(showToList.length > 0) { /* * If we've already listed some suggestions, output a list * separator before starting the next group. */ if(listStarted) say(orListSep); /* Output an introduction to our list of ShowTopics */ DMsg(show, 'show {him interlocutor} '); /* Show the list of suggested ShowTopics */ showList(showToList); /* Note that we have now started listing topics */ listStarted = true; } break; case 'ask for': if(askForList.length > 0) { /* * If we've already listed some suggestions, output a list * separator before starting the next group. */ if(listStarted) say(orListSep); /* Output an introduction to our list of AskForTopics */ DMsg(ask for, 'ask {him interlocutor} for '); /* Show the list of suggested AskForTopics */ showList(askForList); /* Note that we have now started listing topics */ listStarted = true; } break; case 'yes': if(yesList.length > 0) { /* * If we've already listed some suggestions, output a list * separator before starting the next group. */ if(listStarted) say(orListSep); /* Show our list of YesTopics (typically, just 'say yes') */ showList(yesList); /* Note that we have now started listing topics */ listStarted = true; } break; case 'no': if(noList.length > 0) { /* * If we've already listed some suggestions, output a list * separator before starting the next group. */ if(listStarted) say(orListSep); /* Show our list of NoTopics (typically, just 'say no') */ showList(noList); /* Note that we have now started listing topics */ listStarted = true; } break; case 'command': if(commandList.length > 0) { /* * If we've already listed some suggestions, output a list * separator before starting the next group. */ if(listStarted) say(orListSep); /* Output an introduction to our list of CommandTopics */ DMsg(tell to, 'tell {him interlocutor} to '); /* Show the list of suggested CommandTopics */ showList(commandList); /* Note that we have now started listing topics */ listStarted = true; } break; } } // end JF mods /* * Finish the list by appending its suffix */ showListSuffix(lst, nil, explicit); } /* Show one of our sublists of particular kinds of suggest topics */ showList(lst) { /* For each element in the list */ for(local cur in lst, local i = 1 ;; ++i) { /* * If the current topic entry wants to include a sayPrefix, * displat the sayPrefix. In practice this only applies to * SayTopics which may or may not want to introduce the name of a * suggestion with 'say'. */ if(cur.includeSayInName) say(sayPrefix); /* Display the name of the current suggestion */ say(cur.name); /* Output a comma or 'or', depending where we are in the list */ if(i == lst.length - 1) DMsg(or, ' or '); if(i < lst.length - 1) ", "; } } /* * The typeInfo contains a list of lists that are used by the show method * to build our various sublists. The first element of each list is a * pointer to the list property to use on this lister object to hold the * particular sublist. The second element of each list is a property * pointer used to identify which sublist a TopicEntry belongs in, * according to its own includeInList property. The third element is the * type of topic entry a topic entry should be suggested as if it is * explicitly requested in its suggestAs property. */ typeInfo = [ [&sayList, &sayTopics, SayTopic, nil], [&queryList, &queryTopics, QueryTopic, BMsg(ask query, 'ask {him interlocutor} ')], [&askList, &askTopics, AskTopic, BMsg(ask about, 'ask {him interlocutor} about ')], [&tellList, &tellTopics, TellTopic, BMsg(tell about, 'tell {him interlocutor} about ')], [&talkList, &talkTopics, TalkTopic, BMsg(talk about, 'talk about ')], [&giveList, &giveTopics, GiveTopic, BMsg(give, 'give {him interlocutor} ')], [&showToList, &showTopics, ShowTopic, BMsg(show, 'show {him interlocutor} ')], [&askForList, &askForTopics, AskForTopic, BMsg(ask for, 'ask {him interlocutor} for ')], [&yesList, &miscTopics, YesTopic, nil], [&noList, &miscTopics, NoTopic, nil], [&commandList, &commandTopics, CommandTopic, BMsg(tell to, 'tell {him interlocutor} to ')] ] /* Sublists of each kind of suggestion which can be listed in turn */ sayList = [] queryList = [] askList = [] tellList = [] talkList = [] giveList = [] showToList = [] yesList = [] noList = [] askForList = [] commandList = [] /* * Test whether the topicEntry t includes prop in its includeInList. */ includes(t, prop) { return t.includeInList.indexOf(prop) != nil; } /* * The prefix to use when suggesting a SayTopic, if it explicitly wants * the suggestion to start with 'say'. */ sayPrefix = BMsg(say prefix, 'say ') /* The conjunction to use at the end of a list of alternatives */ orListSep = BMsg(or list separator, '; or ') ;