Source code for evennia.utils.verb_conjugation.conjugate

"""
English verb conjugation

Original Author: Tom De Smedt <tomdesmedt@organisms.be> of Nodebox
Refactored by Griatch 2021, for Evennia.

This is distributed under the GPL2 license. See ./LICENSE.txt for details.

The verb.txt morphology was adopted from the XTAG morph_englis.flat:
http://www.cis.upenn.edu/~xtag/


"""

import os

_VERBS_FILE = "verbs.txt"

# Each verb and its tenses is a list in verbs.txt,
# indexed according to the following keys:
# the negated forms (for supported verbs) are ind+11.

verb_tenses_keys = {
    "infinitive": 0,
    "1st singular present": 1,
    "2nd singular present": 2,
    "3rd singular present": 3,
    "present plural": 4,
    "present participle": 5,
    "1st singular past": 6,
    "2nd singular past": 7,
    "3rd singular past": 8,
    "past plural": 9,
    "past": 10,
    "past participle": 11,
}

# allow to specify tenses with a shorter notation
verb_tenses_aliases = {
    "inf": "infinitive",
    "1sgpres": "1st singular present",
    "2sgpres": "2nd singular present",
    "3sgpres": "3rd singular present",
    "pl": "present plural",
    "prog": "present participle",
    "1sgpast": "1st singular past",
    "2sgpast": "2nd singular past",
    "3sgpast": "3rd singular past",
    "pastpl": "past plural",
    "ppart": "past participle",
}

# Each verb has morphs for infinitve,
# 3rd singular present, present participle,
# past and past participle.
# Verbs like "be" have other morphs as well
# (i.e. I am, you are, she is, they aren't)
# Additionally, the following verbs can be negated:
# be, can, do, will, must, have, may, need, dare, ought.

# load the conjugation forms from ./verbs.txt
verb_tenses = {}

path = os.path.join(os.path.dirname(__file__), _VERBS_FILE)
with open(path) as fil:
    for line in fil.readlines():
        wordlist = [part.strip() for part in line.split(",")]
        verb_tenses[wordlist[0]] = wordlist

# Each verb can be lemmatised:
# inflected morphs of the verb point
# to its infinitive in this dictionary.
verb_lemmas = {}
for infinitive in verb_tenses:
    for tense in verb_tenses[infinitive]:
        if tense:
            verb_lemmas[tense] = infinitive


[docs]def verb_infinitive(verb): """ Returns the uninflected form of the verb, like 'are' -> 'be' Args: verb (str): The verb to get the uninflected form of. Returns: str: The uninflected verb form of `verb`. """ return verb_lemmas.get(verb, "")
[docs]def verb_conjugate(verb, tense="infinitive", negate=False): """ Inflects the verb to the given tense. Args: verb (str): The single verb to conjugate. tense (str): The tense to convert to. This can be given either as a long or short form - "infinitive" ("inf") - be - "1st/2nd/3rd singular present" ("1/2/3sgpres") - am/are/is - "present plural" ("pl") - are - "present participle" ("prog") - being - "1st/2nd/3rd singular past" ("1/2/3sgpast") - was/were/was - "past plural" ("pastpl") - were - "past" - were - "past participle" ("ppart") - been negate (bool): Negates the verb. This only supported for a limited number of verbs: be, can, do, will, must, have, may, need, dare, ought. Returns: str: The conjugated verb. If conjugation fails, the original verb is returned. Examples: The verb 'be': - present: I am, you are, she is, - present participle: being, - past: I was, you were, he was, - past participle: been, - negated present: I am not, you aren't, it isn't. """ tense = verb_tenses_aliases.get(tense, tense) verb = verb_infinitive(verb) ind = verb_tenses_keys[tense] if negate: ind += len(verb_tenses_keys) try: return verb_tenses[verb][ind] except IndexError: # TODO implement simple algorithm here with +s for certain tenses? return verb
[docs]def verb_present(verb, person="", negate=False): """ Inflects the verb in the present tense. Args: person (str or int): This can be 1, 2, 3, "1st", "2nd", "3rd", "plural" or "*". negate (bool): Some verbs like be, have, must, can be negated. Returns: str: The present tense verb. Example: had -> have """ person = str(person).replace("pl", "*").strip("stndrgural") mapping = { "1": "1st singular present", "2": "2nd singular present", "3": "3rd singular present", "*": "present plural", } if person in mapping and verb_conjugate(verb, mapping[person], negate) != "": return verb_conjugate(verb, mapping[person], negate) return verb_conjugate(verb, "infinitive", negate)
[docs]def verb_present_participle(verb): """ Inflects the verb in the present participle. Args: verb (str): The verb to inflect. Returns: str: The inflected verb. Examples: give -> giving, be -> being, swim -> swimming """ return verb_conjugate(verb, "present participle")
[docs]def verb_past(verb, person="", negate=False): """ Inflects the verb in the past tense. Args: verb (str): The verb to inflect. person (str, optional): The person can be specified with 1, 2, 3, "1st", "2nd", "3rd", "plural", "*". negate (bool, optional): Some verbs like be, have, must, can be negated. Returns: str: The inflected verb. Examples: give -> gave, be -> was, swim -> swam """ person = str(person).replace("pl", "*").strip("stndrgural") mapping = { "1": "1st singular past", "2": "2nd singular past", "3": "3rd singular past", "*": "past plural", } if person in mapping and verb_conjugate(verb, mapping[person], negate) != "": return verb_conjugate(verb, mapping[person], negate) return verb_conjugate(verb, "past", negate=negate)
[docs]def verb_past_participle(verb): """ Inflects the verb in the present participle. Args: verb (str): The verb to inflect. Returns: str: The inflected verb. Examples: give -> given, be -> been, swim -> swum """ return verb_conjugate(verb, "past participle")
[docs]def verb_all_tenses(): """ Get all all possible verb tenses. Returns: list: A list if string names. """ return list(verb_tenses_keys.keys())
[docs]def verb_tense(verb): """ Returns a string from verb_tenses_keys representing the verb's tense. Args: verb (str): The verb to check the tense of. Returns: str: The tense. Example: given -> "past participle" """ infinitive = verb_infinitive(verb) data = verb_tenses[infinitive] for tense in verb_tenses_keys: if data[verb_tenses_keys[tense]] == verb: return tense if data[verb_tenses_keys[tense] + len(verb_tenses_keys)] == verb: return tense
[docs]def verb_is_tense(verb, tense): """ Checks whether the verb is in the given tense. Args: verb (str): The verb to check. tense (str): The tense to check. Return: bool: If verb matches given tense. """ tense = verb_tenses_aliases.get(tense, tense) return verb_tense(verb) == tense
[docs]def verb_is_present(verb, person="", negated=False): """ Checks whether the verb is in the present tense. Args: verb (str): The verb to check. person (str): Check which person. negated (bool): Check if verb was negated. Returns: bool: If verb was in present tense. """ person = str(person).replace("*", "plural") tense = verb_tense(verb) if tense is not None: if "present" in tense and person in tense: if not negated: return True elif "n't" in verb or " not" in verb: return True return False
[docs]def verb_is_present_participle(verb): """ Checks whether the verb is in present participle. Args: verb (str): The verb to check. Returns: bool: Result of check. """ tense = verb_tense(verb) return tense == "present participle"
[docs]def verb_is_past(verb, person="", negated=False): """ Checks whether the verb is in the past tense. Args: verb (str): The verb to check. person (str): The person to check. negated (bool): Check if verb is negated. Returns: bool: Result of check. """ person = str(person).replace("*", "plural") tense = verb_tense(verb) if tense is not None: if "past" in tense and person in tense: if not negated: return True elif "n't" in verb or " not" in verb: return True return False
[docs]def verb_is_past_participle(verb): """ Checks whether the verb is in past participle. Args: verb (str): The verb to check. Returns: bool: The result of the check. """ tense = verb_tense(verb) return tense == "past participle"
[docs]def verb_actor_stance_components(verb): """ Figure out actor stance components of a verb. Args: verb (str): The verb to analyze Returns: tuple: The 2nd person (you) and 3rd person forms of the verb, in the same tense as the ingoing verb. """ tense = verb_tense(verb) if "participle" in tense or "plural" in tense: return (verb, verb) if tense == "infinitive" or "present" in tense: you_str = verb_present(verb, person="2") or verb them_str = verb_present(verb, person="3") or verb + "s" else: you_str = verb_past(verb, person="2") or verb them_str = verb_past(verb, person="3") or verb + "s" return (you_str, them_str)