forked from vantablack/vantaMOO
implement pronounsub
This commit is contained in:
parent
488595e2b8
commit
8daecbf9fc
|
@ -18,11 +18,12 @@ from evennia import default_cmds
|
|||
|
||||
from evennia.contrib.base_systems.building_menu import GenericBuildingCmd
|
||||
from evennia.contrib.game_systems import mail
|
||||
from evennia.contrib.game_systems.multidescer import CmdMultiDesc
|
||||
from evennia.contrib.grid.ingame_map_display import MapDisplayCmdSet
|
||||
from evennia.contrib.grid import simpledoor
|
||||
from lib.rpsystem.rpsystem import RPSystemCmdSet
|
||||
from evennia.contrib.game_systems.clothing import ClothedCharacterCmdSet
|
||||
from evennia.contrib.game_systems.multidescer import CmdMultiDesc
|
||||
from evennia.contrib.grid import simpledoor
|
||||
from evennia.contrib.grid.ingame_map_display import MapDisplayCmdSet
|
||||
from lib.pronounsub import SetPronouns
|
||||
from lib.rpsystem.rpsystem import RPSystemCmdSet
|
||||
|
||||
|
||||
class CharacterCmdSet(default_cmds.CharacterCmdSet):
|
||||
|
@ -65,6 +66,9 @@ class CharacterCmdSet(default_cmds.CharacterCmdSet):
|
|||
# Clothing: wear
|
||||
self.add(ClothedCharacterCmdSet())
|
||||
|
||||
# gendersub
|
||||
self.add(SetPronouns())
|
||||
|
||||
class AccountCmdSet(default_cmds.AccountCmdSet):
|
||||
"""
|
||||
This is the cmdset available to the Account at all times. It is
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
from .pronounsub import PronounCharacter
|
||||
from .pronounsub import SetPronouns
|
|
@ -0,0 +1,262 @@
|
|||
"""
|
||||
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 random
|
||||
import re
|
||||
|
||||
from evennia import Command, DefaultCharacter
|
||||
from evennia.utils import logger
|
||||
|
||||
# gender maps
|
||||
|
||||
# TODO: Don't make this hardcoded.
|
||||
_PRONOUN_LIST = [
|
||||
{"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"},
|
||||
]
|
||||
|
||||
_PRONOUN_FORMS = [ "s", "o", "p", "a" ]
|
||||
|
||||
_RE_GENDER_PRONOUN = re.compile(r"(?<!\|)\|(?!\|)[sSoOpPaA]")
|
||||
|
||||
# in-game command for setting the gender
|
||||
|
||||
|
||||
class SetPronouns(Command):
|
||||
"""
|
||||
Sets your pronouns.
|
||||
|
||||
Usage:
|
||||
@gender
|
||||
@gender <pronoun1>[;pronoun2 ...]
|
||||
|
||||
With no arguments, this command prints your current pronouns.
|
||||
|
||||
Pronouns can be specified either in a general form, like "she/they", or a
|
||||
specific form, like "they,them,their,theirs".
|
||||
|
||||
For the general form, each in the list must match up to a grammatical form
|
||||
of a specific pronoun in a known database, and that specific pronoun will
|
||||
be used.
|
||||
|
||||
The specific format is: <subjective>,<objective>,<possessive>,<absolute>
|
||||
subjective: *They* went to the store.
|
||||
objective: You took *them* to the store.
|
||||
possessive: You took *their* friend to the store.
|
||||
absolute: The sandwich in the fridge was *theirs*.
|
||||
|
||||
When multiple pronouns are given, a random one will be used in each text
|
||||
substitution.
|
||||
|
||||
Examples:
|
||||
@pronouns he/him
|
||||
|
||||
@pronouns she/they/it
|
||||
|
||||
@pronouns they,them,their,thers
|
||||
|
||||
@pronouns she/they;fae,faer,faer,faers
|
||||
"""
|
||||
|
||||
key = "pronouns"
|
||||
locks = "call:all()"
|
||||
|
||||
def __init__(self):
|
||||
self.cmd_type = "set"
|
||||
self.syntax_error = False
|
||||
|
||||
def parse(self):
|
||||
|
||||
self.cmd_type = "set"
|
||||
self.syntax_error = True
|
||||
|
||||
generals = []
|
||||
specifics = []
|
||||
|
||||
if self.args == '':
|
||||
self.cmd_type = "get"
|
||||
self.syntax_error = False
|
||||
return
|
||||
|
||||
pronouns = self.args.strip().lower().split(";")
|
||||
|
||||
for pronoun in pronouns:
|
||||
slash = ('/' in pronoun)
|
||||
comma = (',' in pronoun)
|
||||
if slash and comma:
|
||||
return
|
||||
|
||||
if comma:
|
||||
specific = [ p.strip() for p in pronoun.split(",") ]
|
||||
if len(specific) != len(_PRONOUN_FORMS):
|
||||
return
|
||||
|
||||
new = {}
|
||||
for i in range(len(specific)):
|
||||
new[_PRONOUN_FORMS[i]] = specific[i]
|
||||
specifics.append(new)
|
||||
else:
|
||||
generals += [ p.strip() for p in pronoun.split("/") ]
|
||||
|
||||
self.args = (generals, specifics)
|
||||
self.syntax_error = False
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
||||
if self.syntax_error:
|
||||
caller.msg(self.get_help(caller, self.cmdset))
|
||||
return
|
||||
|
||||
if self.cmd_type == "get":
|
||||
caller.msg(f"Your pronouns are \"{caller._print_pronouns()}\"")
|
||||
return
|
||||
|
||||
generals, specifics = self.args
|
||||
|
||||
for general in generals:
|
||||
if not caller._specific_pronoun_from_general(general):
|
||||
caller.msg(f"Warning: The general pronoun \"{general}\" is not"
|
||||
"in the server's list of pronouns. It will be"
|
||||
"ignored.")
|
||||
|
||||
caller.db.pronoun_generals = generals
|
||||
caller.db.pronoun_specifics = specifics
|
||||
caller.msg(f"Your pronouns have been set to \"{caller._print_pronouns()}\".")
|
||||
|
||||
class PronounCharacter(DefaultCharacter):
|
||||
"""
|
||||
This is a Character class aware of gender.
|
||||
|
||||
"""
|
||||
|
||||
def at_object_creation(self):
|
||||
"""
|
||||
Called once when the object is created.
|
||||
"""
|
||||
super().at_object_creation()
|
||||
self.db.pronoun_generals = [ "they", "them" ]
|
||||
self.db.pronoun_specifics = []
|
||||
|
||||
def _specific_pronoun_from_general(self, general):
|
||||
for pronoun in _PRONOUN_LIST:
|
||||
if general in pronoun.values():
|
||||
return pronoun
|
||||
|
||||
return None
|
||||
|
||||
def _print_pronouns(self):
|
||||
generals = self.attributes.get("pronoun_generals", default=[ "they", "them" ])
|
||||
specifics = self.attributes.get("pronoun_specifics", default=[])
|
||||
res = [ "/".join(generals) ] if len(generals) else []
|
||||
for specific in specifics:
|
||||
res.append(",".join([ specific[form] for form in _PRONOUN_FORMS ]))
|
||||
return ";".join(res)
|
||||
|
||||
|
||||
def _get_pronoun(self, regex_match):
|
||||
logger.log_info("hereee " + str(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
|
||||
logger.log_info("hereee " + typ)
|
||||
dup_specifics = self.attributes.get("pronoun_specifics", default=[])
|
||||
for general in self.attributes.get("pronoun_generals", default=[ "they", "them" ]):
|
||||
specific = self._specific_pronoun_from_general(general)
|
||||
if specific != None:
|
||||
dup_specifics.append(specific)
|
||||
|
||||
specifics = []
|
||||
for s in dup_specifics:
|
||||
if not s in specifics:
|
||||
specifics.append(s)
|
||||
|
||||
choice = random.choice(specifics)
|
||||
|
||||
gender = self.attributes.get("gender", default="ambiguous")
|
||||
gender = gender if gender in ("male", "female", "neutral") else "ambiguous"
|
||||
|
||||
pronoun = choice[typ.lower()]
|
||||
logger.log_info("hereee " + pronoun)
|
||||
return pronoun.capitalize() if typ.isupper() else pronoun
|
||||
|
||||
def msg(self, text=None, from_obj=None, session=None, **kwargs):
|
||||
"""
|
||||
Emits something to a session attached to the object.
|
||||
Overloads the default msg() implementation to include
|
||||
gender-aware markers in output.
|
||||
|
||||
Args:
|
||||
text (str or tuple, optional): The message to send. This
|
||||
is treated internally like any send-command, so its
|
||||
value can be a tuple if sending multiple arguments to
|
||||
the `text` oob command.
|
||||
from_obj (obj, optional): object that is sending. If
|
||||
given, at_msg_send will be called
|
||||
session (Session or list, optional): session or list of
|
||||
sessions to relay to, if any. If set, will
|
||||
force send regardless of MULTISESSION_MODE.
|
||||
Notes:
|
||||
`at_msg_receive` will be called on this Object.
|
||||
All extra kwargs will be passed on to the protocol.
|
||||
|
||||
"""
|
||||
if text is None:
|
||||
super().msg(from_obj=from_obj, session=session, **kwargs)
|
||||
return
|
||||
|
||||
try:
|
||||
if text and isinstance(text, tuple):
|
||||
text = (_RE_GENDER_PRONOUN.sub(self._get_pronoun, text[0]), *text[1:])
|
||||
else:
|
||||
text = _RE_GENDER_PRONOUN.sub(self._get_pronoun, text)
|
||||
except TypeError:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.log_trace(e)
|
||||
super().msg(text, from_obj=from_obj, session=session, **kwargs)
|
|
@ -8,8 +8,16 @@ creation commands.
|
|||
|
||||
"""
|
||||
from lib.rpsystem import ContribRPCharacter
|
||||
from lib.pronounsub import PronounCharacter
|
||||
from evennia.contrib.game_systems.clothing import ClothedCharacter
|
||||
|
||||
# rpsystem
|
||||
class Character(ContribRPCharacter, ClothedCharacter):
|
||||
pass
|
||||
class Character(ContribRPCharacter, ClothedCharacter, PronounCharacter):
|
||||
def at_object_creation(self):
|
||||
super(PronounCharacter, self).at_object_creation()
|
||||
super(ContribRPCharacter, self).at_object_creation()
|
||||
|
||||
def msg(self, text=None, from_obj=None, session=None, **kwargs):
|
||||
# TODO: Don't do this. See https://git.disroot.org/vantablack/vantaMOO/issues/29
|
||||
super(PronounCharacter, self).msg(text, from_obj, session, **kwargs)
|
||||
#super(ContribRPCharacter, self).msg(text, from_obj, session, **kwargs)
|
||||
|
|
Loading…
Reference in New Issue