Dialogue is not character-dependent
That is to say -- you can't set conditions for a specific character to speak a certain way.
I don't mean "in French" (per se), but to use different words or phrases.
All dialogue seems to be handled by... different parts of the Character class
- move_to
- live
- converse
- discuss
- decide_what_to_do_about
- converse
... and are not externally exposed (are they?), so they can't be modified/extended without modifying core code.
At any rate -- these notes are for making your engine more generic for my potential purposes and not making it more useful for your definite purposes. So it goes.
In a larger scheme of things, beyond character dialogue, the "tone" of narration cannot be changed. This is a more core issue of the engine -- f'r instance, passive voice or anything else of variance.
Point about generic and definite purposes noted. During November, I might be more concerned with my own definite purposes, but it looks like this is shaping up to something that might exist beyond November, so, yes, we can at least discuss it and identify how it could be made more generic...
The main weakness, as I see it, is that each Event object is built around a "phrase", which is a template, like <1> went to <2>. Obviously, this makes them tied to English, and worse, to particular phrasing in English (tense, choice of words, etc.) Ideally, Events would be more abstract than that. For instance, you could instead have a MoveEvent for that purpose, and it could be the Editor's job to select an appropriate phrase for rendering that Event as an English sentence (or in present tense or in Spanish or whatever.) (This is assuming that it's the Editor's responsibility to set the "tone of narration", which I think is reasonable.)
The problem with that is that it's a pain to manage this extra level of abstraction, especially when you're just hacking away at code, trying to get your ideas out. (A solution to that might be to make it optional. I'll think about it.)
As to how the classes are structured:
The Animate class is the base class for things that can move on their own accord, while, currently, Character is The Swallows-specific. The idea is that you (presumably) make characters for your own story by subclassing Animate to your own Character class. You'd implement the live method, and you'd call the methods on Character in that implementation, such as move_to, pick_up, and so forth.
(For the moment, I can probably add a better example of doing this sort of thing, to not_the_swallows.py.)
discuss, converse, and decide_what_to_do_about are Character-specific, because they do control very story-specific logic*, but I agree that they could and probably should be generalized somehow. Although, again, doing so while not imposing a particular sort of dialogue style might be a little difficult. (If you've ever played games written in Inform, with the standard Inform libraries, you notice that they tend to have a similar "voice", aspects of which date all the way back to the original Zork, or rather, MIT's Dungeon -- but I digress.)
One idea I've had is to make an intermediate class, maybe called Sentient, which is part of the engine, and thus generic, and establishes a framework for conversing/discussing. Character would then be a subclass of Sentient. In writing your own story, you could either subclass Sentient for your characters -- in which case they would provide stock reactions for anything you haven't overridden -- or you could copy and customize it, or just write your own, if you wanted to have the characters have a very different dialogue style.
Hope this all makes some sort of sense.
*Heck, they used to be one big method, until I could not stand the deep indentation any longer.
With regard to Event objects -- what about taking a page out of predicate logic's book and saying that an event is a named relationship between two or more objects (which could be Characters or Events)? Then, the structure of how an Event is turned into words can be implemented separately (and maybe even put into a different class altogether), making it possible to do tenses and randomize phrasing and conjugate verbs based on gender and even do limited kinds of literal translation. In the meantime, to maintain backwards-compatibility, you could have the default string representation reproduce Event's current behavior.
On Mon, Nov 11, 2013 at 9:14 AM, catseye [email protected] wrote:
Point about generic and definite purposes noted. During November, I might be more concerned with my own definite purposes, but it looks like this is shaping up to something that might exist beyond November, so, yes, we can at least discuss it and identify how it could be made more generic...
The main weakness, as I see it, is that each Event object is built around a "phrase", which is a template, like <1> went to <2>. Obviously, this makes them tied to English, and worse, to particular phrasing in English (tense, choice of words, etc.) Ideally, Events would be more abstract than that. For instance, you could instead have a MoveEvent for that purpose, and it could be the Editor's job to select an appropriate phrase for rendering that Event as an English sentence (or in present tense or in Spanish or whatever.) (This is assuming that it's the Editor's responsibility to set the "tone of narration", which I think is reasonable.)
The problem with that is that it's a pain to manage this extra level of abstraction, especially when you're just hacking away at code, trying to get your ideas out. (A solution to that might be to make it optional. I'll think about it.)
As to how the classes are structured:
The Animate class is the base class for things that can move on their own accord, while, currently, Character is The Swallows-specific. The idea is that you (presumably) make characters for your own story by subclassing Animate to your own Character class. You'd implement the live method, and you'd call the methods on Character in that implementation, such as move_to, pick_up, and so forth.
(For the moment, I can probably add a better example of doing this sort of thing, to not_the_swallows.py.)
discuss, converse, and decide_what_to_do_about are Character-specific, because they do control very story-specific logic_, but I agree that they could and probably should be generalized somehow. Although, again, doing so while not imposing a particular sort of dialogue style might be a little difficult. (If you've ever played games written in Inform, with the standard Inform libraries, you notice that they tend to have a similar "voice", aspects of which date all the way back to the original *Zork_, or rather, MIT's Dungeon -- but I digress.)
One idea I've had is to make an intermediate class, maybe called Sentient, which is part of the engine, and thus generic, and establishes a framework for conversing/discussing. Character would then be a subclass of Sentient. In writing your own story, you could either subclass Sentient for your characters -- in which case they would provide stock reactions for anything you haven't overridden -- or you could copy and customize it, or just write your own, if you wanted to have the characters have a very different dialogue style.
Hope this all makes some sort of sense.
*Heck, they used to be one big method, until I could not stand the deep indentation any longer.
— Reply to this email directly or view it on GitHubhttps://github.com/catseye/The-Swallows/issues/3#issuecomment-28202690 .
There is an article on NPC dialogue starting on p331 of IF Theory Reader (PDF) (linked-to from http://nickm.com/if/toward.html ).
Abstraction is not easy - and you should only abstract what you need to abstract. Otherwise: YAGNI.
So, these notes are not nesc. for THIS MONTHS'S implementation.....
Something (potentially?) simple would be to allow for easy addition of stock phrases to a character -- where you now have
if choice == 20:
self.emit("<1> yawned", [self])
elif choice == 21:
self.emit("<1> gazed thoughtfully into the distance", [self])
elif choice == 22:
self.emit("<1> thought <he-1> heard something", [self])
elif choice == 23:
self.emit("<1> scratched <his-1> head", [self])
elif choice == 24:
self.emit("<1> immediately had a feeling something was amiss", [self])
maybe the templates could be part of each Character, can be set externally, and the core picks from those phrases?
I'll look into how to use "Animate" instead of Character. The name reads as a verb-action, primarily....
Hm, that's true; I'm usually fairly pedantic about making sure class names are nouns. I think I'm unconsciously imitating Inform's nomenclature here. Come to think of it, Actor isn't a very good name for a class that includes passive things like locations and treasures, either. I think I'll wait until this has actual version numbers before contemplating renaming such basic things, though.
I agree that setting up a list of stock "idle actions" shouldn't be too hard. At least not for Swallows characters. There could be some method that returns a list of template strings, and it just picks one, and you could override that (for, say, Fred.) In general terms... still not too hard but I'd like to think about just what should be in Sentient first.