vantaMOO/lib/pronounsub/common.py

138 lines
3.9 KiB
Python

"""
Pronounsub
Griatch 2015
Copyright (c) 2023 lunacb <lunacb@disroot.org>
This is a gender-aware Character class that allows people to set pronouns and
use them in text.
Usage
When in use, messages can contain special tags to indicate pronouns gendered
based on the one being addressed. Capitalization will be retained.
- `|s`, `|S`: Subjective form, like They
- `|o`, `|O`: Objective form, like Them
- `|p`, `|P`: Possessive form, like Their
- `|a`, `|A`: Absolute Possessive form, like Theirs
For example,
```
char.msg("%s falls on |p face with a thud." % char.key)
"Tom falls on their face with a thud"
```
To use, have DefaultCharacter inherit from this, or change
setting.DEFAULT_CHARACTER to point to this class.
The `pronouns` command is used to set pronouns. It needs to be added to the
default cmdset before it becomes available.
"""
import copy
import random
import re
from evennia import Command, DefaultCharacter
from evennia import DefaultScript
from evennia import InterruptCommand
from evennia.utils import logger
from evennia.utils.create import create_script
from evennia.utils.search import search_script
class PronounDbScript(DefaultScript):
def at_script_creation(self):
self.db.pronouns = copy.deepcopy(DEFAULT_SPECIFIC_PRONOUNS)
DEFAULT_SPECIFIC_NEUTRAL_PRONOUNS = {"s": "they", "o": "them", "p": "their", "a": "theirs"}
DEFAULT_SPECIFIC_PRONOUNS = [
{"s": "he", "o": "him", "p": "his", "a": "his"},
{"s": "she", "o": "her", "p": "her", "a": "hers"},
{"s": "it", "o": "it", "p": "its", "a": "its"},
{"s": "they", "o": "them", "p": "their", "a": "theirs"}
]
DEFAULT_CHARACTER_PRONOUNS = [ "they", "them" ]
PRONOUN_FORMS = [ "s", "o", "p", "a" ]
RE_GENDER_PRONOUN = re.compile(r"(?<!\|)\|(?!\|)[sSoOpPaA]")
# in-game command for setting the gender
def parse_specific_pronoun(pronoun):
specific = [ p.strip() for p in pronoun.split(",") ]
if len(specific) != len(PRONOUN_FORMS):
return None
new = {}
for i in range(len(specific)):
new[PRONOUN_FORMS[i]] = specific[i]
return new
def get_pronoun_list():
search = search_script("pronoun_db")
if not any(search):
script = create_script("lib.pronounsub.PronounDbScript", key="pronoun_db")
else:
script = search[0]
return script.db.pronouns
def specific_pronoun_from_character(character, caller=None):
pronoun_list = get_pronoun_list()[:]
if caller != None:
pronoun_list = caller.db.pronoun_specs + pronoun_list
for pronoun in pronoun_list:
if character in pronoun.values():
return pronoun
return None
def stringify_specific_pronoun(spec):
return ",".join([ spec[form] for form in PRONOUN_FORMS ])
def stringify_pronouns(character):
pronouns = character.attributes.get("pronouns", default=DEFAULT_CHARACTER_PRONOUNS[:])
return "/".join(pronouns)
def pronoun_repl(character, regex_match):
"""
Get pronoun from the pronoun marker in the text. This is used as
the callable for the re.sub function.
Args:
regex_match (MatchObject): the regular expression match.
Notes:
- `|s`, `|S`: Subjective form, like They
- `|o`, `|O`: Objective form, like Them
- `|p`, `|P`: Possessive form, like Their
- `|a`, `|A`: Absolute Possessive form, like Theirs
"""
typ = regex_match.group()[1] # "s", "O" etc
dup_specifics = []
for pronoun in character.attributes.get("pronouns", default=DEFAULT_CHARACTER_PRONOUNS[:]):
specific = specific_pronoun_from_character(pronoun, character)
if specific != None:
dup_specifics.append(specific)
specifics = []
for s in dup_specifics:
if not s in specifics:
specifics.append(s)
if len(specifics) == 0:
choice = DEFAULT_SPECIFIC_NEUTRAL_PRONOUNS
else:
choice = random.choice(specifics)
pronoun = choice[typ.lower()]
return pronoun.capitalize() if typ.isupper() else pronoun