Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am currently working on a text based game, where the outcome of a combat round goes something like this

%attacker% inflicts a serious wound (12 points damage) on %defender%

Right now, I just swap %attacker% with the name of the attacker, and %defender% for the name of the defender. However, the description works, but don't read correctly. Since the game is just all text, I don't want to resort to generic descriptions (Such as "You use Attack on Goblin for 5 damage", which arguably solve the problem)

How do I generate correct descriptions for cases where %attacker% refers to

  • "You", the player? "You inflicts..." is wrong
  • "Bees", or other plural? I need somehow to know I should prefix the name with a "The "
  • If %attacker% is a generic noun, such as "Goblin", it will read weird as opposed to %attacker% being a name. Compare "Goblin inflicts..." vs. "Aldraic Swordbringer inflicts...."

How does text-based games usually resolve such issues?

share|improve this question
add comment

4 Answers

up vote 8 down vote accepted

The %attacker% approach can be extended to include some information other than just the names of the objects:

  1. The verb may be singular or plural. This depends on the subject. "You attack X" (singular 2nd person subject) vs. "Extrakun attacks X" (singular 3rd person subject) vs. "The goblins attack X" (plural 3rd person subject). Most verbs just need an -s added but there are a few exceptions.
  2. The noun may be a proper noun ("Goblin attacks X") or a common noun ("A goblin attacks X"). Common nouns starting with a vowel sound should use "an" instead of "a". It may be a common noun but having only one instance in the current context ("The goblin attacks X").
  3. The noun may vary in number, from zero ("You hit no goblins") to one ("You hit one goblin") to many ("You hit three goblins"). Many nouns just need an -s or -es added but there are many exceptions.
  4. Subjects and objects may be simple ("A goblin") or compound ("A goblin and her brother").
  5. Common nouns at the beginning of the sentence need to be capitalized, but if the noun has an article or if it's compound you want to only capitalize the first word. Proper nouns are always capitalized.
  6. The subject position ("She hit the goblin") and object position ("The goblin hit her") use different pronouns.
  7. Possessives can be generated by adding 's if singular ("A goblin's axe"), ' if plural ("Two goblins' axes"), but pronouns have their own rules ("Your axe").

For English, I wrote Python a text generation library derived from a MUD called JaysHouseMOO. Feel free to study or copy the code. It doesn't have a good library of exceptional cases; you'll have to add that with the words used in your game. I'm afraid my ported code isn't extensively tested. It might also need more cases added for games (it was designed for a social MUD, not a gaming MUD).

Your example would be written as "%1I %1:(inflicts) a serious wound (%2n damage) on %3i". The numbers %1, %2, %3 tell it which object is to be substituted; I/i tell it to add an indirect article ("a", "an") if needed; n tells it to display the noun without articles; :(inflicts) tells it to conjugate the verb for that object.

Here's the output to show to the attacker, the defender, and to everyone else:

$ python
>>> import msg
>>> m = "%1I %1:(inflicts) a serious wound (%2n damage) on %3i."
>>> attacker = msg.GenderedObject('Amit', 'm', 'proper')
>>> defender = msg.GenderedObject('goblin', 'm', 'unique')
>>> points = (12, 'point')
>>> msg.Msg().sub_parties({1: attacker, 2: points, 3: defender}, 
                          m, [attacker, defender])
(['You inflict a serious wound (12 points damage) on the goblin.', 
  'Amit inflicts a serious wound (12 points damage) on you.'], 
 'Amit inflicts a serious wound (12 points damage) on the goblin.')

Note if you had given it (1, 'point') it would have printed "1 point" instead of "1 points". That's something that bugs me in game text, so I made sure to include a feature to make it easy to print that properly.

Here's another example, with compound nouns, and "a" vs. "an":

>>> m = "%1I %1:(hits) %2'n %2'(head)."
>>> a1 = msg.GenderedObject('goblin', 'm', 'normal')
>>> a2 = msg.GenderedObject('orc', 'm', 'normal')
>>> d1 = msg.GenderedObject('Amit', 'm', 'proper')
>>> d2 = msg.GenderedObject('Extrakun', 'm', 'proper')
>>> msg.Msg().sub_parties({1: [a1, a2], 2: [d1, d2]}, m, [d1, d2])
(["A goblin and an orc hit your and Extrakun's heads.", 
  "A goblin and an orc hit Amit's and your heads."], 
 "A goblin and an orc hit Amit's and Extrakun's heads.")

These examples are in English, and only track male/female, pronouns, singular/plural verbs/nouns, and proper/common nouns. What you need to track will vary across languages and the type of text in your game. In Spanish there are formal and informal pronouns. Several languages have masculine and feminine forms of verbs. Japanese pronouns depend on the status of the subject relative to the object. In some languages the verb conjugation can implicitly include the subject. Determine all the kinds of text you want to generate and the languages you want to translate to, and that'll tell you what you need to track in your game objects. When you're creating the content, you can include the necessary annotations and exceptional cases.

share|improve this answer
1  
+1, great summary of the issues. One thing I'll add is that players tend to be pretty forgiving of minor grammatical errors for generated text like this as long as the rest of the information (damage amount, source, target, procs) is accurate - shoot for 95% correct grammar, because the last 5% is ridiculously hard. –  user744 Jan 8 '11 at 14:52
add comment

There is a set of modules for Perl starting with Lingua::EN::Inflect that deals with these issues. Even if you're using a different language, the API choices made might help you frame your own design.

share|improve this answer
    
Nifty! There's a Python port of this library too: pypi.python.org/pypi/inflect/0.2.1 –  amitp Jan 9 '11 at 6:59
add comment

Instead of having a single string, and trying to substitute into it properly, you could have a whole set of them. Start with the objects. You know, when creating the mob, what to refer to it as. You can give it a specific property, separate from it's name, for substituting into attack strings. Weapons can have multiple strings for variety, and can substitute in more detail. Instead of 'attacker', they can ask specifically for 'attacker-pronoun' or 'attacker-propername'. Mobs can have plural versions of these identifiers too, if your 'bees' are represented by multiple mobs and not just a single mob that happens to be called 'bees'.

So you would have a mob like

name = goblin
pronoun = he
plural = goblins
proper = goblin
common = a goblin
specific_common = the goblin
possessive = the goblin's
possessive_pronoun = his

Then your attack string asks for specific items like so..

%attacker-pronoun% hit %defender-specific_common% for %damage%! %defender-pronoun% really felt that one!

share|improve this answer
add comment

The way I handle this is through a large set of systemry that, among other things, involves modeling the message as a data structure rather than a string. The values for the attacker and the defender are their actual objects; the verb ("inflict" in your message) is marked as such, and knows the object for the person performing it, so that the message renderer knows that it needs to be displayed in first person to the actor and second person to everybody else. Objects also know whether their nouns are proper or not (and therefore, whether "the" or "a/an" should ever be applied to them), there are data models that allow me to specify that "the" or "a/an" would normally be expected to be applied to a non-proper noun in that position, and a lot more.

This thread on Mudconnector is very similar to your question, and I go into my system's details extensively there. Basically, the way I do it is what you would want if you want to be completely unconstrained by your messaging system's underlying capabilities and are willing to pay a price in learning curve for that. (Much like vi vs. nano.)

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.