code:
Most writing is basically just plain text with branches for different cases.
Important cases to remember:
-Does the slave have a dick/vagina/tits?
-Does the PC have a dick/tits/vagina?
-If the slave has a dick and you plan to use it, can they get erect on their own?
-Is the PC pregnant?
-Is the slave mindbroken?
-Is the slave blind?
-Is the slave pregnant?
-If you penetrate an orifice, is the slave a virgin in that orifice?
-Can the slave move (i.e. is the slave amputated and/or have massive tits and/or a massive dick)?
-Does the slave like/hate trust/fear you?
-Does the slave have fetishes or personality/sexual quirks/flaws that would impact how they react?

It's important to handle every RELEVANT variation of the above cases. Depending on what you're writing, other cases may also warrant consideration; e.g. a breast-play scene will probably need to account for breast size and lactation a lot more than a generic fuck scene. If a scene only applies to a specific type of slave, you can restrict the cases you account for to the ones that are only possible for that type of slave.

There are, broadly speaking, two main ways to do this:
1. Write the same big block of text and then copy/paste it into each relevant case, and tweak the wording slightly.
 ++Less thinking required
 --LOTS of duplicate text; if you need to change something later, you have to change it in many places
2. Decompose the scene into smaller segments or sections that can each be swapped out for the slave type in question.
 ++MUCH easier maintenance
 --Have to figure out how to phrase the scene in a way that can be broken down into discrete chunks

You can also combine the two cases. For example, you may want a complex, interleaved set of <<if>> conditions for the common cases, and then have big blobs for the corner cases that are hard to handle.

It can also be easier if you split the scene into a "prep", "main", and "finish" section (these would all be the same writing block, just 2-3 <<if>> chains in sequence); that way, you could, for example, take all the various possible cases that aren't really unique, and narrate them so that, in the main section, you don't have to do so much explanatory writing for the scene to make sense overall. Then, if necessary, wrap up with the finish section. (See src/pregmod/fSlaveSelfImpreg.tw for an example of this approach)

All the variables for you and the slave are, generally, held in the variables $PC and $activeSlave, respectively. When the PC and the slave have the same attributes, they usually have the same name, but exactly what they do and mean can vary a little bit. RTFM for details. To access a specific variable, you do $var.attribName, so e.g. pregnancy is checked by $activeSlave.preg or $PC.preg. In rarer cases, you'll be dealing with an indexed entry in the $slaves array; if that's the case, you'd use $slaves[_u] or $slaves[$i] (or whatever) instead of $activeSlave. If a second (or third?) slave is present, it will be stored in another variable, the name of which will depend on the scene; for example, when impregnating a slave with another slave, the sperm donor is in $impregnatrix

Conditions are usually checked by
<<if CONDITION>>
	SHOW THIS TEXT
<<elseif CONDITION2>>
	SHOW THIS TEXT INSTEAD
<<else>>
	IF NEITHER CONDITION IS MET, SHOW THIS
<</if>>

Conditions are usually comparative (i.e. $a < $b or $b == 5 or $c != $d.e) and can be chained together with && (and) or || (or) and grouped with parentheses () - for example:
<<if($a > 1 || ($b == 2 && $c != $a))>>
lets you check that either variable A is greater than one, or both B equals two and C is not equal to A.
There are also a few misc functions that let you check things like whether a slave can get pregnant or whether two slaves are mutually fertile

Variable names are interpolated straight into the text, so if you have a slave named "Beth" then the text
"You fuck $activeSlave.slaveName" becomes "You fuck Beth"
You can also explicitly print a variable by doing <<print _varName>> (for temp variables) or <<print $varName>> (for global variables) which can be useful in various situations; it also lets you print the output of code expressions, like <<print $someNumericVar * 10>>.
If you want to change a variable, you do something like
<<set $activeSlave.devotion += 5>>
Which would, in this case, give a devotion increase of 5.

Color is changed with YOUR @@.colorname;COLORED TEXT@@ HERE

So a random (really stupid) example might be:
<<if $activeSlave.fetish == 'mindbroken'>>
	Special big block of mindbroken text here.
<<elseif $activeSlave.amp == 1>>
	Special big block of amputee text here.
<<if $PC.dick > 0>>
	<<set _wasVirgin = ''>>
	<<if $activeSlave.vagina > -1>>
		<<set _orifice = 'vagina'>>
		<<if $activeSlave.vagina == 0>>
			<<set _wasVirgin = 'vaginal'>>
		<</if>>
	<<else>>
		<<set _orifice = 'ass'>>
		<<if $activeSlave.anus == 0>>
			<<set _wasVirgin = "anal">>
		<</if>>
	<</if>>
	You fuck $activeSlave.slaveName's _orifice.
	<<if _wasVirgin != ''>>
		<<if $activeSlave.devotion > 50>>
			She @@.hotpink;loves@@ losing her <<print _wasVirgin>> virginity to you.
			<<set $activeSlave.devotion += 5>>
		<<else>>
			She @@.mediumorchid;@@dislikes losing her <<print _wasVirgin>> virginity to you.
			<<set $activeSlave.devotion -= 5>>
		<</if>>
	<</if>>
<<elseif $PC.vagina > 0 && $activeSlave.dick > 0>>
	$activeSlave.slaveName
	<<if $activeSlave.devotion > 50>>
		@@.hotpink;lovingly penetrates@@
		<<set $activeSlave.devotion += 5>>
	<<else>>
		indifferently hammers
	<</if>>
	your pussy.
<<elseif $activeSlave.vagina > -1>>
	Lesbian sex here.
<<else>>
	ERROR - PC doesn't have dick or vagina?
<</if>>

If you need to set a temp variable, prefix it with _ instead of $. This way, you don't go cluttering up the world with variables that only matter inside your little writing segment.

You can "hot-test" stuff by text editing your HTML copy of FC, but it's a little more tedious because you have to "escape" double quotes, <, >, and & with " < > and & respectively.

Some hints:
1. Write your logic first, so you don't forget to close tags. In other words, it's better to do
<<if $cond>
	TODO
<<else>>
	TODO
<</if>>
And then fill it in later than it is to end up with a situation where you have a dozen unclosed tags and you can't remember where they are or what they do.

2. For very simple stuff, it's fine to "inline" your stuff. For example, when penetrating a slave, doing "you fuck her <<if $activeSlave.vagina > -1>>pussy<<else>>ass<</if>>" to show "pussy" or "ass" as necessary. However, if you need to do the same comparison a bunch of times, do something like
<<if $activeSlave.vagina > -1>>
	<<set _targetOrifice = "vagina">>
<<else>>
	<<set _targetOrifice = "asshole">>
<</if>>
And then, when you need it, do "you fuck her _targetOrifice" in sixteen different places without having the pain in the ass of copy/pasting the same if/else clause every time.

3. INDENT YOUR LOGIC. USE TABS. I'm serious. Don't question me. It will make EVERYONE hate you, when they have to deal with your code, if it's not indented properly.
This is much easier to read:
<<if $cond1>>
	<<if $cond2>>
		whatever
	<<elseif $cond3>>
		whatever
	<<elseif $cond4>>
		<<if $cond5>>
			whatever
		<<else>>
			<<if $cond6>>
				whatever
			<</if>>
		<</if>>
	<<else>>
		whatever
		<<if $cond7>>
			<<if $cond8>>
				whatever
			<</if>>
		<</if>>
	<</if>>
<</if>>
than this:
<<if $cond1>>
<<if $cond2>>
whatever
<<elseif $cond3>>
whatever
<<elseif $cond4>>
<<if $cond5>>
whatever
<<else>>
<<if $cond6>>
whatever
<</if>>
<</if>>
<<else>>
whatever
<<if $cond7>>
<<if $cond8>>
whatever
<</if>>
<</if>>
<</if>>
<</if>>

4. Proof-read your shit before posting it. Spell-check wouldn't hurt.

repo_name: AmbrosiaCheesecake/fc


code:
# Producing slave lists

The namespace `App.UI.SlaveList` provides functions for displaying lists of slaves and interacting with the slaves in those lists. These functions supersede (and extend) the `Slave Summary` passage. They provide a way to display a list, select a slave from a list, generate standard lists for a facility or a leader selection, as well as provide a way to customize output and interaction.

## General concept

The core function is `App.UI.SlaveList.render()`. It renders the list, assembling it from four pieces. The function is declared as follows:

```js
/**
 * @param {number[]} indices
 * @param {Array.<{index: number, rejects: string[]}>} rejectedSlaves
 * @param {slaveTextGenerator} interactionLink
 * @param {slaveTextGenerator} [postNote]
 * @returns {string}
 */
function (indices, rejectedSlaves, interactionLink, postNote)
```

and the type of the `slaveTextGenerator` callback is:

```js
/**
 * @callback slaveTextGenerator
 * @param {App.Entity.SlaveState} slave
 * @param {number} index
 * @return {string}
 */
```

To build the output, the `render()` function iterates over the `indices` array, which must contain indices from the `$slaves` array, and outputs each slave using the two callbacks. The first one (`interactionLink`) is used to generate the hyperlink for the slave name. Output from the second callback (if defined) will be printed after each slave summary. The array of rejected slaves is processed after that and its contents are printed out in a simple fashion. The function *does not sort* both arrays, neither `indices` nor `rejectedSlaves`; their elements are printed in the order, specified by the caller. The function' output has to be passed via the SugarCube wikifier, for example by printing in out using the `<<print>>` macro.

Let's consider a few examples.

## Implementation examples

### Basic printing

The most common behavior for the slave name links is to go to the `Slave Interact` passage after clicking its name. This is implemented by the `App.UI.SlaveList.SlaveInteract.stdInteract` function:

```js
/**
 * @param {App.Entity.SlaveState} slave
 * @param {number} index
 * @return {string}
 */
App.UI.SlaveList.SlaveInteract.stdInteract = (slave, index) =>
   App.UI.passageLink(SlaveFullName(slave), 'Slave Interact', `$activeSlave = $slaves[${index}]`);
```

The function gets both the slave object and its index in the `$slaves` array for convenience, and outputs a hyperlink in the HTML markup. which points to the `Slave Interact` passage and sets active slave to the slave with the given index, because `Slave Interact` operates with the current slave. In the SugarCube markup the function could look as follows:

```js
/**
 * @param {App.Entity.SlaveState} slave
 * @param {number} index
 * @return {string}
 */
App.UI.SlaveList.SlaveInteract.stdInteract = (slave, index) =>
  `<<link "${SlaveFullName(slave)}" "Slave Interact">><<set $activeSlave = $slaves[${index}]`;
```
Now we can print slave lists. Let's print first three from the `$slaves` array:

```
<<print App.UI.SlaveList.render(
   [0, 1, 2], [].
   App.UI.SlaveList.SlaveInteract.stdInteract
)>>
```

Let's print them in the reverse order:

```
<<print App.UI.SlaveList.render(
   [2, 1, 0], [].
   App.UI.SlaveList.SlaveInteract.stdInteract
)>>
```

and one more time omitting the second slave:

```
<<print App.UI.SlaveList.render(
   [0, 2],
   [{index: 1, rejects: ['Omitted for testing purposes']}].
   App.UI.SlaveList.SlaveInteract.stdInteract
)>>
```

### Post-notes

The post notes are little text pieces, printed after each slave. They can contain simple text, for example to inform that particular slave is special in a way, or provide additional action hyperlinks. The most common type of the post notes is a hyperlink for assigning or retrieving s slave from a facility. Here are their implementations:

```js
(slave, index) => App.UI.passageLink(`Send ${slave.object} to ${facility.name}`, "Assign", `$i = ${index}`);

(slave, index) => App.UI.passageLink(`Retrieve ${slave.object} from ${facility.name}`, "Retrieve", `$i = ${index}`);
```

With these blocks we can easily produce a list of slaves, working at a given facility `facility`.

First, let's get the indices of the workers:

```js
let facilitySlaves = facility.job().employeesIndices();
```

The `App.Entity.Facilities.Facility.job()` call returns a named job if it was given an argument, or the default job when argument was omitted. Pretty much every facility except the penthouse provides only a single job and we can safely omit the job name here.

Now just call the `render()` function:

```js
App.UI.SlaveList.render(facilitySlaves, [],
	App.UI.SlaveList.SlaveInteract.stdInteract,
   (slave, index) => App.UI.passageLink(`Retrieve ${slave.object} from ${facility.name}`, "Retrieve", `$i = ${index}`));
```

That's it, works with any facility.

Here we omitted a few details, like setting the `$returnTo` bookmark for the `Assign` and `Retrieve` passages, sorting the slaves lists, and a few more.

### Templates for common use cases

There are functions in the `App.UI.SlaveList` namespace for a few typical use cases.

Function | Purpose
----- | ----
`listSJFacilitySlaves()` | Creates a tabbed list for assigning and retrieving slaves t0/from a facility with a single job
`displayManager()` | Displays a facility manager with a link to change it or a note with a link to assign a manager
`stdFacilityPage()` | Combines the previous two functions to render the manager and employees
`penthousePage()` | Displays tabs with workers for the penthouse
`slaveSelectionList()` | Displays a list with filtering and sorting links for selecting a slave
`facilityManagerSelection()` | Specialization of the `slaveSelectionList()` to select a manager for a facility, which implements position requirements tests and highlights experienced slaves

### Fully custom lists

There are use cases that stand apart from all other, and there is no point in providing a template for them. In that case you can generate a totally custom list. Here is an example:

```
<<print App.UI.SlaveList.slaveSelectionList(
	s => !ruleSlaveExcluded(s, $currentRule),
	(s, i) => `<u><strong>${App.UI.passageLink(SlaveFullName(s), 'Rules Slave Exclude Workaround', `$activeSlave = $slaves[${i}]`)}</strong></u>`
)>>
```


code:
This brief how-to guides through patching and building sugarcube (https://bitbucket.org/tmedwards/sugarcube)
for the Free Cities. Sugarcube sources can be obtained locally either by cloning its Mercurial
repository or downloading source archive from bitbucket (https://bitbucket.org/tmedwards/sugarcube/downloads/).

Prerequisites (listed NOT in the installation order, please read the list to the end first):
1. Node.js with npm (https://nodejs.org).
2. Mercurial (https://www.mercurial-scm.org/) if you want to clone the sugarcube repository (so it is
optional). Please note that when downloading Windows version, the Mercurial web site lists source
download first (and linked it to the main page), while we need binaries.
3. To build some packages, Node.js requires python and a C/C++ compiler. On Windows you may want to
install Visual Studio (or just the build tools) and Python 2.7 first. As of now, SugarCube does not
depend on any of such packages.

Windows: please choose to make the tools accessible from anywhere by allowing installers to modify
the PATH environment variable.

Retrieving SugarCube sources and preparing build environment for it.
1a. If you opted to use Mercurial, open a terminal window where you want to clone the repository, and
run the following command:
	hg clone https://bitbucket.org/tmedwards/sugarcube
Change working directory into the cloned repository.
Now choose the branch. Let's suppose we want the latest officially released version 2. The branch name
is "v2-release" then:
	hg checkout v2-release
Please note that branch switching in Mercurial requires a clean local tree (without modifications).
To achieve that, run:
	hg update --clean

1b. If you decided not to use Mercurial, you can download a snapshot of a branch or a tag from the
"Downloads" tab of the bitbucket repository page. Unpack it and open a terminal in the directory
with the source files.

2. The last step we need is downloading required JavaScript libraries that are used during the build.
Run the node package manager (npm) in the repository:
	npm install

CAUTION: dependencies list (located in the package.json file in the repository root) may change from
commit to commit and it differs between branches! Make sure to install correct dependencies after switching working branch.

Patching and building SugarCube.

3a. If you opted to use Mercurial, use it to apply the patch:
	hg patch --no-commit <full path to sugarcube-fc-changes.patch>

3b. If you do not use Mercurial:
	patch -p1 < <full path to sugarcube-fc-changes.patch>

Building
Run the build.js script. If you use Git bash, you can run the build.js file directly, otherwise run
it as "node build.js". See "build.js -h" for options, but reasonable sets are the following.
For release version:
	./build.js -b 2
and for the debug version:
	./build.js -b 2 -u -d

Find result files in the dist directory.

APPENDIX Lists required steps very briefly.

1. Clone Sugarcube repo: hg clone https://bitbucket.org/tmedwards/sugarcube
2. Change active directory into the directory of the sugarcube clone.
3. Set active branch to "v2-release": hg checkout v2-release
4. Run npm install in the repo dir.

CAUTION: Requited dependencies change during the project lifetime and vary from branch to branch;
you may need to run npm install again after some time, or after branch/tag change. Try to run it in
case of strange build errors.

The next is done in the directory where SC repo was cloned. Loop over required SugarCube versions:

1. hg update --clean to clean any local changes
2. hg checkout v2.28.2 (any tag or head here, of course)
3. hg patch --no-commit ~/games/fc-pregmod/devNotes/sugarcube\ stuff/sugarcube-fc-changes.patch
4. node build.js -b 2 to build release version
5. cp dist/twine2/sugarcube-2/format.js <whenever you want>
6. node build.js -b 2 -u -d to build debug version
7. cp dist/twine2/sugarcube-2/format.js <whenever you want to place the debug header>


code:
There are two main changes here.

CHANGE 1: Speed up loading
==========================

The first is to speed up loading the file.

Edit the sugarcube header and change:

	{key:"_serialize",value:function(e)
	...
	 return Object.freeze

	 {return LZString.compressToUTF16(JSON.stringify(e))}},{key:"_deserialize",value:function(e){return JSON.parse(LZString.decompressFromUTF16(e))}}]),e}();

Into this

[{key:"_serialize",value:function(e)

/* look here for changes */
{return JSON.stringify(e)}},{key:"_deserialize",value:function(e){return JSON.parse((!e || e[0]=="{")?e:LZString.decompressFromUTF16(e))}}]),e}();
/* changes end here */

return Object.freeze

CHANGE 2: Remember scroll position
==================================

Edit the sugarcube header and change:

	var t=jQuery(this);t.ariaIsDisabled()||(t.is("[aria-pressed]")&&t.attr("aria-pressed","true"===t.attr("aria-pressed")?"false":"true"),e.apply(this,arguments))

into this:

	var t=jQuery(this);
	const dataPassage = t.attr('data-passage');
	const initialDataPassage = window && window.SugarCube && window.SugarCube.State && window.SugarCube.State.passage;
	const savedYOffset = window.pageYOffset;
	t.is("[aria-pressed]")&&t.attr("aria-pressed","true"===t.attr("aria-pressed")?"false":"true"),e.apply(this,arguments);
	const doJump = function(){ window.scrollTo(0, savedYOffset); }
	if ( dataPassage && (window.lastDataPassageLink === dataPassage || initialDataPassage === dataPassage))
		doJump();
	window.lastDataPassageLink = dataPassage;

This uses two separate methods to detect if we are returning to the same page. Just checking sugarcube should actually be sufficient, but no harm in this approach either.

CHANGE 3: Ignore expired array
==============================

	return e?t.history=clone(R):t.delta=O(R),V.length>0&&(t.expired=[].concat(_toConsumableArray(V))),null!==B&&(t.seed=B.seed),t}function n(e,t){

	into

	return e?t.history=clone(R):t.delta=O(R),V.length>0&&(t.expired=[]),null!==B&&(t.seed=B.seed),t}function n(e,t){

CHANGE 4: Save overwriting?
===========================

	d.append(e("load","ui-close",L10n.get("savesLabelLoad"),s,function(e){jQuery(document).one(":dialogclose",function(){

	into

	d.append(e("save","ui-close",L10n.get("savesLabelSave"),s,Save.slots.save),e("load","ui-close",L10n.get("savesLabelLoad"),s,function(e){jQuery(document).one(":dialogclose",function(){

path: devNotes/sugarcube stuff/important for updating sugarcube.txt


code:
diff -r cd5d732c8669 src/lib/jquery-plugins.js
--- a/src/lib/jquery-plugins.js	Fri Mar 09 07:43:39 2018 -0600
+++ b/src/lib/jquery-plugins.js	Fri Jan 25 18:37:15 2019 +0100
@@ -37,6 +37,10 @@
		return function () {
			const $this = jQuery(this);

+			const dataPassage = $this.attr('data-passage');
+			const initialDataPassage = window && window.SugarCube && window.SugarCube.State && window.SugarCube.State.passage;
+			const savedYOffset = window.pageYOffset;
+
			// Toggle "aria-pressed" status, if the attribute exists.
			if ($this.is('[aria-pressed]')) {
				$this.attr('aria-pressed', $this.attr('aria-pressed') === 'true' ? 'false' : 'true');
@@ -44,6 +48,11 @@

			// Call the true handler.
			fn.apply(this, arguments);
+
+			const doJump = function(){ window.scrollTo(0, savedYOffset); }
+			if ( dataPassage && (window.lastDataPassageLink === dataPassage || initialDataPassage === dataPassage))
+				doJump();
+			window.lastDataPassageLink = dataPassage;
		};
	}

diff -r cd5d732c8669 src/lib/simplestore/adapters/webstorage.js
--- a/src/lib/simplestore/adapters/webstorage.js	Fri Mar 09 07:43:39 2018 -0600
+++ b/src/lib/simplestore/adapters/webstorage.js	Fri Jan 25 18:37:15 2019 +0100
@@ -192,11 +192,11 @@
		}

		static _serialize(obj) {
-			return LZString.compressToUTF16(JSON.stringify(obj));
+			return JSON.stringify(obj);
		}

		static _deserialize(str) {
-			return JSON.parse(LZString.decompressFromUTF16(str));
+			return JSON.parse((!str || str[0] == "{") ? str : LZString.decompressFromUTF16(str));
		}
	}

diff -r cd5d732c8669 src/state.js
--- a/src/state.js	Fri Mar 09 07:43:39 2018 -0600
+++ b/src/state.js	Fri Jan 25 18:37:15 2019 +0100
@@ -104,7 +104,7 @@
		}

		if (_expired.length > 0) {
-			stateObj.expired = [..._expired];
+			stateObj.expired = [];
		}

		if (_prng !== null) {
diff -r cd5d732c8669 src/ui.js
--- a/src/ui.js	Fri Mar 09 07:43:39 2018 -0600
+++ b/src/ui.js	Fri Jan 25 18:37:15 2019 +0100
@@ -337,6 +337,7 @@
				if (saves.slots[i]) {
					// Add the load button.
					$tdLoad.append(
+						createButton('save', 'ui-close', L10n.get('savesLabelSave'), i, Save.slots.save),
						createButton('load', 'ui-close', L10n.get('savesLabelLoad'), i, slot => {
							jQuery(document).one(':dialogclose', () => Save.slots.load(slot));
						})


code:
diff -r df721eb4cd55 src/lib/jquery-plugins.js
--- a/src/lib/jquery-plugins.js	Sun Dec 16 04:39:00 2018 -0600
+++ b/src/lib/jquery-plugins.js	Fri Jan 25 00:54:01 2019 +0100
@@ -43,14 +43,9 @@
		return function () {
			const $this = jQuery(this);

-			// Exit if the element is disabled.
-			//
-			// NOTE: This should only be necessary for elements which are not disableable
-			// per the HTML specification as disableable elements should be made inert
-			// automatically.
-			if ($this.ariaIsDisabled()) {
-				return;
-			}
+			const dataPassage = $this.attr('data-passage');
+			const initialDataPassage = window && window.SugarCube && window.SugarCube.State && window.SugarCube.State.passage;
+			const savedYOffset = window.pageYOffset;

			// Toggle "aria-pressed" status, if the attribute exists.
			if ($this.is('[aria-pressed]')) {
@@ -59,6 +54,11 @@

			// Call the true handler.
			fn.apply(this, arguments);
+
+			const doJump = function(){ window.scrollTo(0, savedYOffset); }
+			if ( dataPassage && (window.lastDataPassageLink === dataPassage || initialDataPassage === dataPassage))
+				doJump();
+			window.lastDataPassageLink = dataPassage;
		};
	}

diff -r df721eb4cd55 src/lib/simplestore/adapters/webstorage.js
--- a/src/lib/simplestore/adapters/webstorage.js	Sun Dec 16 04:39:00 2018 -0600
+++ b/src/lib/simplestore/adapters/webstorage.js	Fri Jan 25 00:54:01 2019 +0100
@@ -189,11 +189,11 @@
		}

		static _serialize(obj) {
-			return LZString.compressToUTF16(JSON.stringify(obj));
+			return JSON.stringify(obj);
		}

		static _deserialize(str) {
-			return JSON.parse(LZString.decompressFromUTF16(str));
+			return JSON.parse((!str || str[0] == "{") ? str : LZString.decompressFromUTF16(str));
		}
	}

diff -r df721eb4cd55 src/state.js
--- a/src/state.js	Sun Dec 16 04:39:00 2018 -0600
+++ b/src/state.js	Fri Jan 25 00:54:01 2019 +0100
@@ -104,7 +104,7 @@
		}

		if (_expired.length > 0) {
-			stateObj.expired = [..._expired];
+			stateObj.expired = [];
		}

		if (_prng !== null) {
diff -r df721eb4cd55 src/ui.js
--- a/src/ui.js	Sun Dec 16 04:39:00 2018 -0600
+++ b/src/ui.js	Fri Jan 25 00:54:01 2019 +0100
@@ -334,6 +334,7 @@
				if (saves.slots[i]) {
					// Add the load button.
					$tdLoad.append(
+						createButton('save', 'ui-close', L10n.get('savesLabelSave'), i, Save.slots.save),
						createButton('load', 'ui-close', L10n.get('savesLabelLoad'), i, slot => {
							jQuery(document).one(':dialogclose', () => Save.slots.load(slot));
						})


code:
#!/bin/sh

# setup:
# add this to crontab:
# */15 * * * * cd ~/FC/fc-pregmod && git pull --ff-only origin pregmod-master > ~/FC/git_pull.log 2>&1
# and do "ln -s ~/FC/fc-pregmod/devTools/BuildAndIPFSify.sh .git/hooks/post-merge"
# NOTE: you may need to define XDG_RUNTIME_DIR in your crontab

# TODO: add logic to figure out if we should use ipfs-cluster instead of using the local instance directly.
#			if we use ipfs-cluster we probably don't need to warm ipfs.io's cache.

rm bin/*.html

# if this script is used as the post-merge hook then
# a) git pull has pulled something
# b) $PWD is fc-pregmod
if [ "$(basename "$0")" != "post-merge" ]; then
	# cd to fc-pregmod based on where this script is
	cd "$(readlink -f "$(dirname "$0")")/.." || exit 1
	git pull
	# if there are new html files then git probably pulled something and ran this script as a post-merge hook
	if ls bin/*.html; then
		exit 0
	fi
fi

# If we've done this before then unpin the previous hash so IPFS can GC it if it needs to
if [ -r ../IPFS_hash.txt ]; then
	ipfs pin rm --recursive=true "$(cut -d : -f 2 ../IPFS_hash.txt | tr -d ' ')"
fi

./compile || exit 1

# Keep the build time from changing the hash of the file
sed -Ei -e '/^  \* Built on .+$/d' bin/*.html

# add the date of the last commit to the file, but don't use colons because Windows (still?) doesn't like them
mv bin/*.html "bin/FC pregmod $(git log -1 --format='%cd' --date='format:%F %H-%M').html"

# include the unembedded vector art
ipfs_hash="$(ipfs add -w -Q -r bin/*.html resources)"
echo "IPFS Folder Hash: ${ipfs_hash}" > ../IPFS_hash.txt
ipfs name publish "$ipfs_hash"

# when it's done it will print something like "Published to $your_pubkey: /ipfs/$ipfs_hash"
# You can view the folder at http://127.0.0.1:8080/ipns/$your_pubkey

# make ipfs.io cache the files
# $XDG_RUNTIME_DIR SHOULD be defined, but there are cases where it wouldn't be
if [ -z "${XDG_RUNTIME_DIR+x}" ]; then
	echo "\$XDG_RUNTIME_DIR is unset, bailing"
	exit 2
fi

# throw it into a file so we can loop over lines, not "strings delimited by whitespace"
find resources bin -print | grep -ve '.gitignore' | sed -e 's|bin/||' | grep -Ee '.+\.svg' -e '.html' > "${XDG_RUNTIME_DIR}/files.list"

# ipfs PeerID, it's user specific
PeerID="$(ipfs config show | grep -e 'PeerID' | cut -d: -f 2 | tr -d ' "')"
while IFS= read -r item
do
	echo "https://ipfs.io/ipns/${PeerID}/${item}"
done < "${XDG_RUNTIME_DIR}/files.list" | xargs --max-procs=10 --max-args=1 --replace curl --silent --show-error --range 0-499 --output /dev/null '{}'

rm "${XDG_RUNTIME_DIR}/files.list"


code:
#!/bin/sh U=$1 P=$2 rDir=$3 lDir=$4 repo=$5 Reqs:MEGAcmd,minify,git
mega-login $1 $2;echo 'New clone? 0:y 1:n 2:na';read Opt
while true;do cd $4;gen=0
	if [ $Opt == 0 ];then mkdir -p $4&&git clone -q --depth 1 $5 $4&&cd $4&&if [[ ! `mega-ls $3|cut -c29-32|paste -sd,` =~ `git log|head -1|cut -c8-11` ]];then gen=1;fi #arraryCheck:stackoverflow.com/a/15394738
	elif [[ $Opt > 0||$gen < 1 ]];then git fetch -q&&if [ `git rev-list ...origin --count` -gt 0 ];then git reset -q --hard&&git pull -q&&gen=1;fi ;fi #gitCheck:stackoverflow.com/a/17192101
	if [[ $Opt > 1||$gen > 0 ]];then rm bin/*;minify -rao $4 $4&&./compile.sh -q&&cd bin/&&mv *.h* FC-pregmod-`git log -1 --format=%cd --date=format:%m-%d-%Y-%H-%M`-`git log|head -1|cut -c8-11`.html&&mega-put -c *.h* $3&&mega-rm $3`mega-ls $3|sort -r|tail -n +11`;fi
Opt=-1;clear;sleep 15m;done


code:
#!/usr/bin/env python3
import fileinput
import re
import sys

WARNING = '\033[93m'
ENDC = '\033[0m'

def myprint(*args):
	print(WARNING, fileinput.filename() + ":", ENDC,*args)

def yield_line_and_islastline(f):
	global filename
	global linenumber
	try:
		prevline = next(f)
		filename = fileinput.filename()
		linenumber = fileinput.filelineno()
	except StopIteration:
		return
	for line in f:
		yield (prevline, f.isfirstline())
		filename = fileinput.filename()
		linenumber = fileinput.filelineno()
		prevline = line
	yield prevline, True

pattern = re.compile(r'(<<(\/?) *(if|for|else|switch|case|replace|link)[^<>]*)')

tagfound = []
try:
	for line, isLastLine in yield_line_and_islastline(fileinput.input()):
		for (whole,end,tag) in re.findall(pattern,line):
			if tag == "else" or tag == 'case':
				if len(tagfound) == 0:
					myprint("Found", tag, "but with no opening tag:")
					myprint("  ", linenumber,":", whole)
					fileinput.nextfile()
				lasttag = tagfound[-1]
				if (tag == "else" and lasttag["tag"] != "if") or (tag == "case" and lasttag["tag"] != "switch"):
					myprint("Mismatched else: Opening tag was:")
					myprint("  ",lasttag["linenumber"],":", lasttag["whole"])
					myprint("But this tag was:")
					myprint("  ",linenumber,":", whole)
					fileinput.nextfile()
					break
			elif end != '/':
				tagfound.append({"whole": whole, "linenumber":linenumber,"tag":tag})
			else:
				if len(tagfound) == 0:
					myprint("Found closing tag but with no opening tag:")
					myprint("  ", linenumber,":", whole)
					fileinput.nextfile()
					break
				lasttag = tagfound.pop()
				if lasttag["tag"] != tag:
					myprint("Mismatched tag: Opening tag was:")
					myprint("  ",lasttag["linenumber"],":", lasttag["whole"])
					myprint("Closing tag was:")
					myprint("  ",linenumber,":", whole)
					fileinput.nextfile()
					break

		if isLastLine:
			if len(tagfound) != 0:
				myprint("End of file found but", len(tagfound), ("tag hasn't" if len(tagfound)==1 else "tags haven't"), "been closed:")
			for tag in tagfound:
				myprint("  ", tag["linenumber"],":", tag["whole"])
			tagfound = []
except UnicodeDecodeError as e:
	myprint(e)
	print("   Hint: In Linux, you can get more details about Unicode errors by running:")
	print("	 isutf8", fileinput.filename())
	print("   :Note it might be caused by ", filename)


code:
#!/bin/sh

#converts files in the current dir

# collect files with [script] tag
FILES=`grep '\[script\]' -H -R * | cut -f 1 -d ':'`
for f in $FILES; do
	# create new name. Old name can have any of the following suffixes:
	# _JS.tw  JS.tw .tw
	nf="${f%_JS.tw}"
	nf="${nf%JS.tw}"
	nf="${nf%.tw}"
	# we might end up with an empty name, then set dir name as the file name
	[ -z "$(basename $nf)" -o "${nf: -1}" = "/" ] && nf="${nf}$(basename ${nf})"
	# append the new suffix
	nf="${nf}.js"
	echo "renaming ${f} -> ${nf}"
	# rename the file
	git mv "${f}" "${nf}" || echo "renaming ${f} failed"
	# strip Twee header from it
	sed -i 1d "${nf}" || echo "stripping Twee header failed for ${nf}"
	# strip leading empty line '/./,$!d'
	sed -i '/./,$!d' "${nf}" || echo "Stripping leading empty blank lines failed for ${nf}"
done


code:
# Define phrases that should be searched in src/ on every call of the java based
# sanityCheck here.
# Phrases will be found whenever that exact phrase appears, regardless of
# surroundings or overlapping.
# Format is: searchPhrase#errorMessage
# Output is: Found searchPhrase; Error: errorMessage
cash +=#Should be cashX()
cash -=#Should be cashX()
rep +=#Should be repX()
rep -=#Should be repX()
cash+=#Should be cashX()
cash-=#Should be cashX()
rep+=#Should be repX()
rep-=#Should be repX()
attepmts#attempts
youreslf#yourself
advnaces#advances
canAcheive#canAchieve
setBellySize#SetBellySize
SetbellySize#SetBellySize
setbellySize#SetBellySize
bellypreg#bellyPreg
bellyimplant#bellyImplant
bellyfluid#bellyFluid
carress#caress
hormonebalance#hormoneBalance
fetishknown#fetishKnown
recieve#receive
recieves#receives
$slave[#Should be $slaves[
can not#cannot
Coca Cola#Coca-Cola
dosen't#doesn't