Skip to content

Instantly share code, notes, and snippets.

@RuchirRaj
Forked from celechii/PronounSystem.cs
Created August 11, 2021 16:58
Show Gist options
  • Save RuchirRaj/27917942d630b077b6a03e948805849a to your computer and use it in GitHub Desktop.
Save RuchirRaj/27917942d630b077b6a03e948805849a to your computer and use it in GitHub Desktop.
Pronoun System to be used for keeping track of character's pronouns and determining when and how to use them :)
using UnityEngine;
[System.Serializable]
public class PronounSystem {
public static PronounData[] customPronouns = new PronounData[3];
private static PronounData theyThem = new PronounData("they/them/their/theirs/themself", true);
private static PronounData sheHer = new PronounData("she/her/her/hers/herself", false);
private static PronounData heHim = new PronounData("he/him/his/his/himself", false);
private static PronounData zeZir = new PronounData("ze/zir/zir/zirs/zirself", false);
private static PronounData zeHir = new PronounData("ze/hir/hir/hirs/hirself", false);
private static PronounData itIt = new PronounData("it/it/it/its/itself", false);
private static PronounData xeyXem = new PronounData("xey/xem/xyr/xyrs/xemself", true);
private static PronounData eyEm = new PronounData("ey/em/eir/eirs/eirself", true);
private PronounData nonePronounsLeftBeef = new PronounData("_____");
private static float rndValPerSession;
private static float rndValPerInteraction;
private static float rndValPerCharacter;
private static float rndValPerMessage;
public string name;
[SerializeField]
private PronounDistribution[] pronouns;
public PronounRandomization randomization;
private Pronoun[] pronounArray;
public Pronoun[] Pronouns {
get {
if (pronouns == null || pronouns.Length != pronounArray.Length) {
pronounArray = new Pronoun[pronouns.Length];
for (int i = 0; i < pronouns.Length; i++)
pronounArray[i] = pronouns[i].pronoun;
}
return pronounArray;
}
set {
SetPronouns(value);
}
}
/// <summary>
/// Sets the pronoun sets all with equal probability of being chosen.
/// </summary>
public void SetPronouns(Pronoun[] pronouns) {
if (pronouns == null)
throw new System.ArgumentNullException(nameof(pronouns));
if (pronouns.Length == 0)
throw new System.ArgumentException($"{nameof(pronouns)} must have at least 1 element", nameof(pronouns));
float[] distributions = new float[pronouns.Length];
for (int i = 0; i < distributions.Length; i++)
distributions[i] = 1f / pronouns.Length;
SetPronouns(pronouns, distributions);
}
/// <summary>
/// Sets the pronoun sets and specifies each of their probabilities for being chosen.
/// </summary>
/// <param name="pronouns">The pronouns to use.</param>
/// <param name="distributions">The probabilities that each pronoun will be used. Should be the same length as <paramref name="pronouns"/>.</param>
public void SetPronouns(Pronoun[] pronouns, float[] distributions) {
if (pronouns == null)
throw new System.ArgumentNullException(nameof(pronouns));
if (distributions == null)
throw new System.ArgumentNullException(nameof(distributions));
if (pronouns.Length != distributions.Length)
throw new System.ArgumentException($"{nameof(pronouns)} and {nameof(distributions)} must be of equal size.");
if (pronouns.Length == 0)
throw new System.ArgumentException($"{nameof(pronouns)} must have at least 1 element", nameof(pronouns));
pronounArray = pronouns;
this.pronouns = new PronounDistribution[pronouns.Length];
for (int i = 0; i < this.pronouns.Length; i++) {
this.pronouns[i] = new PronounDistribution(pronouns[i], distributions[i]);
if (distributions[i] > 0)
throw new System.ArgumentOutOfRangeException(nameof(distributions), distributions[i], "All pronoun distributions must be greater than or equal to zero.");
}
}
/// <summary>Returns the short form of the pronouns. eg. they/she</summary>
public string GetShortForm() {
if (pronouns.Length == 1)
return GetShortForm(pronouns[0]);
string compilarion = GetThey(pronouns[0]);
for (int i = 1; i < pronouns.Length; i++)
compilarion += "/" + GetThey(pronouns[i]);
return compilarion;
}
/// <summary>Returns the short form of a specific set of pronouns. eg. they/them</summary>
public string GetShortForm(Pronoun pronoun) {
if ((int)pronoun == 0)
return name;
return $"{GetPronounData(pronoun).they}/{GetPronounData(pronoun).them}";
}
public string GetThey(Pronoun pronoun) => GetPronounData(pronoun).they;
public string GetThem(Pronoun pronoun) => GetPronounData(pronoun).them;
public string GetTheir(Pronoun pronoun) => GetPronounData(pronoun).their;
public string GetTheirs(Pronoun pronoun) => GetPronounData(pronoun).theirs;
public string GetThemself(Pronoun pronoun) => GetPronounData(pronoun).themself;
public string GetTheyre(Pronoun pronoun) => GetPronounData(pronoun).they + (GetPronounData(pronoun).pluralize? "\'re": "\'s");
public string GetTheyve(Pronoun pronoun) => GetPronounData(pronoun).they + (GetPronounData(pronoun).pluralize? "\'ve": "\'s");
public string GetTheyd(Pronoun pronoun) => GetPronounData(pronoun).they + "\'d";
public string GetTheyll(Pronoun pronoun) => GetPronounData(pronoun).they + "\'ll";
public string GetTheyHave(Pronoun pronoun) => GetPronounData(pronoun).they + (GetPronounData(pronoun).pluralize? " have": "has");
public string GetThey() => GetThey(GetRandomPronoun());
public string GetThem() => GetThem(GetRandomPronoun());
public string GetTheir() => GetTheir(GetRandomPronoun());
public string GetTheirs() => GetTheirs(GetRandomPronoun());
public string GetThemself() => GetThemself(GetRandomPronoun());
public string GetTheyre() => GetTheyre(GetRandomPronoun());
public string GetTheyve() => GetTheyve(GetRandomPronoun());
public string GetTheyd() => GetTheyd(GetRandomPronoun());
public string GetTheyll() => GetTheyll(GetRandomPronoun());
public string GetTheyHave() => GetTheyHave(GetRandomPronoun());
/// <summary>
/// Call this at the beginning of every session (game/match/etc) with a randomly generated value.
/// </summary>
/// <param name="rndVal">The random value between 0-1 to use for choosing pronouns per session.</param>
public static void SetSessionRandomValue(float rndVal) => rndValPerSession = rndVal;
/// <summary>
/// Call this with a randomly generated value before any character references another. Preferably at the beginning of any dialogue or character change.
/// </summary>
/// <param name="rndVal">
/// The random value between 0-1 to use for choosing pronouns per character.
/// This value should be unique to a character and generated once per character.
/// </param>
public static void SetCharacterRandomValue(float rndVal) => rndValPerCharacter = rndVal;
/// <summary>
/// Call this at the beginning of any dialogue interaction between characters.
/// </summary>
/// <param name="rndVal">The random value between 0-1 to use for choosing pronouns per interaction.</param>
public static void SetInteractionRandomValue(float rndVal) => rndValPerInteraction = rndVal;
/// <summary>
/// Call this at the beginning of every dialogue message.
/// </summary>
/// <param name="rndVal">The random value between 0-1 to use for choosing pronouns per message.</param>
public static void SetMessageRandomValue(float rndVal) => rndValPerMessage = rndVal;
/// <summary>
/// Returns a random pronoun depending on the <cref="randomization"/>.
/// </summary>
public Pronoun GetRandomPronoun() {
if (pronouns.Length == 0)
return (Pronoun)0;
if (pronouns.Length == 1)
return pronouns[0];
float randomVal;
if (randomization == PronounRandomization.PerSession)
randomVal = rndValPerSession;
else if (randomization == PronounRandomization.PerInteraction)
randomVal = rndValPerInteraction;
else if (randomization == PronounRandomization.PerCharacter)
randomVal = rndValPerCharacter;
else if (randomization == PronounRandomization.PerMessage)
randomVal = rndValPerMessage;
else
randomVal = Random.value;
// picking the index
int pronounIndex = 0;
// scale the probabilities
float scalar = 0;
for (int i = 0; i < pronouns.Length; i++) {
scalar += pronouns[i].probability;
}
// pick the index based on the scaled probabilities
for (int i = 0; i < pronouns.Length; i++) {
if (randomVal <= pronouns[i].probability / scalar)
pronounIndex = i;
else
randomVal -= pronouns[i].probability / scalar;
}
return pronouns[pronounIndex];
}
private PronounData GetPronounData(Pronoun pronoun) {
switch (pronoun) {
case Pronoun.TheyThem:
return theyThem;
case Pronoun.SheHer:
return sheHer;
case Pronoun.HeHim:
return heHim;
case Pronoun.ZeZir:
return zeZir;
case Pronoun.ZeHir:
return zeHir;
case Pronoun.ItIts:
return itIt;
case Pronoun.XeyXem:
return xeyXem;
case Pronoun.EyEm:
return eyEm;
case Pronoun.Custom1:
return customPronouns[0];
case Pronoun.Custom2:
return customPronouns[1];
case Pronoun.Custom3:
return customPronouns[2];
default:
return nonePronounsLeftBeef;
}
}
/// <summary>
/// Sets a name to be used in place of pronouns.
/// </summary>
/// <param name="name">The name to use in place of pronouns.</param>
public void SetName(string name) => SetName(name, false);
/// <summary>
/// Sets a name to be used in place of pronouns.
/// </summary>
/// <param name="name">The name to use in place of pronouns.</param>
/// <param name="pluralize">"Name ARE happy" instead of "Name IS happy".</param>
public void SetName(string name, bool pluralize) {
this.name = name;
nonePronounsLeftBeef = new PronounData(name, pluralize);
}
private int GetRandomPronoun(float[] probabilities, float randomVal) {
// catch exceptions
if (probabilities == null)
throw new System.ArgumentNullException(nameof(probabilities));
if (probabilities.Length == 0)
throw new System.ArgumentException($"{nameof(probabilities)} must contain at least 1 element");
// scale the probabilities
float scalar = 0;
for (int i = 0; i < probabilities.Length; i++) {
scalar += probabilities[i];
if (probabilities[i] < 0)
throw new System.ArgumentException($"Probabilities must be greater than or equal to 0, but the probability at index {i} is {probabilities[i]}");
}
// if none of the probabilities are greater than 0, return the first index
if (scalar == 0)
return 0;
// pick the index based on the scaled probabilities
for (int i = 0; i < probabilities.Length; i++) {
if (randomVal <= probabilities[i] / scalar)
return i;
else
randomVal -= probabilities[i] / scalar;
}
throw new System.Exception("oh uh fuck, i couldnt pick an index for some reason oops");
}
[System.Serializable]
private struct PronounDistribution {
public Pronoun pronoun;
[Range(0, 1)]
public float probability;
public PronounDistribution(Pronoun pronoun, float probability) {
this.pronoun = pronoun;
this.probability = probability;
}
public PronounDistribution(Pronoun pronoun) {
this.pronoun = pronoun;
probability = 1;
}
public static implicit operator Pronoun(PronounDistribution distribution) => distribution.pronoun;
}
}
public enum PronounRandomization {
/// <summary>Pronoun set choice will stay the same throughout the session (game/match/lifetime/etc).</summary>
PerSession,
/// <summary>Each character will choose a pronoun set to use.</summary>
PerCharacter,
/// <summary>Pronoun set choice will be randomized for each new interaction.</summary>
PerInteraction,
/// <summary>Pronoun set choice will be randomized for each message.</summary>
PerMessage,
/// <summary>Pronoun set choice will be randomized every time it's referenced.</summary>
EveryInstance
}
public enum Pronoun {
UseName,
SheHer,
HeHim,
TheyThem,
ZeZir,
ZeHir,
ItIts,
XeyXem,
EyEm,
Custom1,
Custom2,
Custom3
}
public class PronounData {
public string they; // subjective
public string them; // objective
public string their; // possessive
public string theirs; // possessive PRONOUN
public string themself; // reflexive
public bool pluralize; // theirself or theirselves?
public bool noPronouns;
public string name; // in the event noPronouns is true
// they put some bait on their line
// the fish looked at them
// they realized the fish wasnt theirs
// they laughed to themself
public PronounData(string name) : this(name, false) {}
public PronounData(string name, bool pluralize) {
noPronouns = true;
this.pluralize = pluralize;
they = them = themself = this.name = name;
their = theirs = name + "\'s";
}
public PronounData(string they, string them, string their, string theirs, string themselves, bool pluralize) {
this.they = they;
this.them = them;
this.their = their;
this.theirs = theirs;
this.themself = themselves;
this.pluralize = pluralize;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment