Cleaning up pronoun code

Twine Version: 2.3.9
Story Format: SugarCube 2.31.1

Hi, I’m making my first ever game and have a question.

I’m working on an IF story/game with a set group of characters that the player interacts with to solve mysteries/learn stuff/etc. The stories of those characters do not change, but one thing that is randomized per Story are their pronouns.

The code I’ve written functions as intended, but it feels like I’m doing just a metric ton of copying and pasting and I know in the back of my mind that there’s gotta be a cleaner way to do it and will likely help make me write more efficiently in the long run.

Currently, I have in StoryInit this character initialization for everyone:

/* The Star */

<<set $Star = {
	fullname: ...,
	firstname: ...,
	lastname: ...,
	pronouns: either ("hehim", "sheher", "theythem", "theyshe", "theyhe"),
}>>\
<<StarPronouns>>

/* The Captain */ 

<<set $Captain = {
	fullname: ...,
	firstname: ...,
	lastname: ...,
	pronouns: either ("hehim", "sheher", "theythem", "theyshe", "theyhe"),
}>>\
<<CaptainPronouns>>

And then, in the Pronouns Widget passage, I have this for each character:

/* The Star */

<<widget "StarPronouns">>\
<<nobr>>\
	<<if $Star.pronouns is "hehim">>\
		<<set $Star.they to "he">>\
		<<set $Star.them to "him">>\
		<<set $Star.their to "his">>\
		<<set $Star.theirs to "his">>\
		<<set $Star.theyre to "he's">>\
	<<elseif $Star.pronouns is "sheher">>\
		<<set $Star.they to "she">>\
		<<set $Star.them to "her">>\
		<<set $Star.their to "hers">>\
		<<set $Star.theirs to "hers">>\
		<<set $Star.theyre to "she's">>\
	<<elseif $Star.pronouns is "theythem">>\
		<<set $Star.they to "they">>\
		<<set $Star.them to "them">>\
		<<set $Star.their to "their">>\
		<<set $Star.theirs to "theirs">>\
		<<set $Star.theyre to "they're">>\
	<<elseif $Star.pronouns is "theyshe">>\
		<<set $Star.they to either ("they", "she")>>\
		<<set $Star.them to either ("them", "her")>>\
		<<set $Star.their to either ("their", "hers")>>\
		<<set $Star.theirs to either ("theirs", "hers")>>\
		<<set $Star.theyre to either ("they're", "she's")>>\
	<<elseif $Star.pronouns is "theyhe">>\
		<<set $Star.they to either ("they", "he")>>\
		<<set $Star.them to either ("them", "him")>>\
		<<set $Star.their to either ("their", "his")>>\
		<<set $Star.theirs to either ("theirs", "his")>>\
		<<set $Star.theyre to either ("they're", "he's")>>\
	<</if>>
<</nobr>>
<</widget>>

/* Captain */

<<widget "CaptainPronouns">>\
<<nobr>>\
	<<if $Captain.pronouns is "hehim">>\
		<<set $Captain.they to "he">>\
		<<set $Captain.them to "him">>\
		<<set $Captain.their to "his">>\
		<<set $Captain.theirs to "his">>\
		<<set $Captain.theyre to "he's">>\
	<<elseif $Captain.pronouns is "sheher">>\
		<<set $Captain.they to "she">>\
		<<set $Captain.them to "her">>\
		<<set $Captain.their to "hers">>\
		<<set $Captain.theirs to "hers">>\
		<<set $Captain.theyre to "she's">>\
	<<elseif $Captain.pronouns is "theythem">>\
		<<set $Captain.they to "they">>\
		<<set $Captain.them to "them">>\
		<<set $Captain.their to "their">>\
		<<set $Captain.theirs to "theirs">>\
		<<set $Captain.theyre to "they're">>\
	<<elseif $Captain.pronouns is "theyshe">>\
		<<set $Captain.they to either ("they", "she")>>\
		<<set $Captain.them to either ("them", "her")>>\
		<<set $Captain.their to either ("their", "hers")>>\
		<<set $Captain.theirs to either ("theirs", "hers")>>\
		<<set $Captain.theyre to either ("they're", "she's")>>\
	<<elseif $Captain.pronouns is "theyhe">>\
		<<set $Captain.they to either ("they", "he")>>\
		<<set $Captain.them to either ("them", "him")>>\
		<<set $Captain.their to either ("their", "his")>>\
		<<set $Captain.theirs to either ("theirs", "his")>>\
		<<set $Captain.theyre to either ("they're", "he's")>>\
	<</if>>
<</nobr>>
<</widget>>

etc.
etc. 

(Yes, I know there are a lot of escapes, I got frustrated trying to find what was doing it and just took the nuclear option. Feel free to show me how to clean that up as well.)

Anyway, it’s outputting how I want, but I feel like it’s working twice as hard to do half as much? The usage is to do something like this:

$Captain.firstname shrugs at the question, fiddling with $Captain.their microphone. "I don't know. You'll have to ask $Star.them."  

(I’m also having an issue with “they are” vs. “he is” verbs, not really liking what solutions I’ve seen thus far, but I think this topic is getting bloated as is.)

Any help to tighten this up would be much appreciated.

You might want to take a look at the “Pronoun Templates” section of my Twine/SugarCube sample code collection. It shows how to use SugarCube’s Template API to make that kind of stuff a bit cleaner/simpler.

If you add a “gender” property to your characters, using “m” (male), “f” (female), “n” (gender neutral), or “b” (non-gendered) for each, then you could do this:

<<SetGender $Captain.gender>>$Captain.firstname shrugs at the question, fiddling with ?their microphone. "I don't know. You'll have to ask<<SetGender $Star.gender>> ?them."

The <<SetGender>> widget just needs to be called once like that, until you need to change genders. The templated words, like ?their and ?them, will display the appropriate gendered version of those pronouns instead.

Hope that helps! :slight_smile:

1 Like

Hey, HiEv,

I like this! Thank you! Lemme see how I can adjust it. Basically, what I’m trying to do is sidestep the specification of gender entirely.

For example, my partner is non-binary, but uses they/she pronouns. A friend identifies as male but prefers to use both they and he pronouns. So I’m wanting to exit those checkboxes to a certain degree.

Let’s say 3 = “theyshe” and we set $pgen to 3. How could I make:

Template.add("they", function () { return ["he", "she", "they", "it"][State.variables.pgen]; });

INTO:

Template.add("they", function () { return ["he", "she", "they", /* SOMETHING THAT DOES SOMETHING LIKE either("they", "she") */][State.variables.pgen]; });

Where when you use ?they, it randomly chooses one or the other .

Does that make sense? Is that possible?

Yeah, it’s possible. It’s just JavaScript. Do it however you want.

For example, you could simply override what happens when $pgen is set to 3:

Template.add("they", function () {
	if (State.variables.pgen === 3) {
		return either("they", "she");
	}
	return ["he", "she", "they", "it"][State.variables.pgen];
});

Instead of returning “it”, that template would now randomly return either “they” or “she” when $pgen is set to 3. (Note that, if a “return” is called, any other code after that line of code is not executed, since it then “returns” to the code that called the function with the value generated on that “return” line.)

Enjoy! :slight_smile:

As an alternate solution you can create arrays with your pronouns.

<<set $nominative to ["he","she","they"]>>
<<set $possessive to ["his","her","their"]>>
<<set $objective to ["him","her","them"]>>

/* The Star */
<<set _gender to random(0,2)>>
<<set $Star = {
	objective: $objective[_gender],
}>>\

/* The Captain */ 
<<set _gender to random(0,2)>>
<<set $Captain = {
	firstname: "Robin",
	possessive: $possessive[_gender],
}>>\

$Captain.firstname shrugs at the question, fiddling with $Captain.possessive microphone. "I don't know. You'll have to ask $Star.objective."

Thanks everyone! These are great options.

@souppilouliouma, I guess my question here, if only for my own edification, is: when I use, say, $Captain.possessive in that example, would it pull either “them” or “he” each time it is used?

In other words, if I use it three times in the same sentence, does it randomly select either term each individual time?

The method Souppilouliouma suggested will only be randomized when you set the properties, which should* be abbreviated like this:

<<set $Star.objective = $objective[random(0, 2)]>>
<<set $Captain.possessive = $possessive[random(0, 2)]>>

However, if you use templates like I suggested, then it would automatically be randomized each time you use the templated word.

(*: I note that if you do the code as Souppilouliouma suggested, it will actually wipe out the other properties of $Star and $Captain, so don’t do it that way.)

Yes, Logan, as I wasn’t explicit at all, that’s a good point. The pronouns are set once and for all with the coding I’ve written. It means pronouns are consistent through time. They also are consistent between them, because there’s only one instance of randomization. Then, someone identifying as female will have ‘she’, ‘her’, ‘her’. Well, as HiEv pointed she would have if the character had .nominative, .objective and .possessive properties.

Please note that, while HiEv shortcut is perfectly valid if you only need one pronoun per character, it might not give consistency should you need more than one pronoun per character.
If you write (beware, not HiEv’s code):

<<set $Captain.objective = $objective[random(0, 2)]>>
<<set $Captain.possessive = $possessive[random(0, 2)]>>

You might end with “him” and “they” for instance. Two times out of three your pronouns won’t match. That’s why I’ve randomized the gender first, determined the pronouns second.

I attempted to copy and paste this code, but my Twine application says it doesn’t recognize it due to “harlowe macros”.

I’m not sure which “this code” you’re referring to, but all of the code in this thread is for Twine games made using the SugarCube story format. If you’re trying to use any of it while using the Harlowe story format, then it won’t work.


But that’s exactly the kind of thing they said that they wanted, for it to randomly produce gendered and non-gendered pronouns. Look at the OP’s example code in their second post.

If they wanted to control which gendered pronoun was used along with the non-gendered pronoun, then if instead of:

<<set $nominative to ["he", "she", "they"]>>

they used:

<<set $nominative to ["he", "they", "she"]>>

Then you could get “he”/“they” by using $nominative[random(0, 1)] and “they”/“she” by using $nominative[random(1, 2)] instead.

However, you’d still have to re-run that code before every use if you wanted it to spit out random results each time.

That’s why the template version is better, because you only have to set a value when swapping the subject, rather than having to re-roll the pronoun every time you want to use it (at which point there’s really no point to storing that data on the character object).

Does that make sense now?

Ah yes, that is my problem.

No problem. That’s why we try to make sure that the threads are all tagged with the appropriate story format. :slight_smile:

1 Like

Correct @HiEv, this is why I like the template way.

Basically, the intention is to replicate how they/[gendered pronoun] people, in my personal experience, generally would like to see their pronouns be used, which is, in the case of “they/she”, would be to have those pronouns used without any weight toward one or the other.

(Reasoning: whenever a person establishes those pronouns for themselves, often other people will revert to what makes them most comfortable. So then a certain group of peers will use “she” exclusively, and others will use “they” exclusively, which isn’t exactly what the person who’s being referred to is asking for.)

So with the template way, I can put down ?they, and if it’s set to “they/she,” then with each instance of ?they it will flip a coin and pull either they or she without me having to set/reset pronouns each and every single time.

When having a predominantly text-based game, that amount of time saved is incredibly useful.