138 lines
3.9 KiB
Python
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
|