Your fetish is [[fetish]]
// Returns an array of traces, each different from the one preceding it unless retrace() maxes out attempts.\n\nwindow.traceArray = function(symbol, num){\n\tvar output = [];\n\toutput.push( trace(symbol) );\n\n\tfor (var i = 1; i < num; i++) {\n\t\toutput.push( retrace(symbol, output[i-1]) );\n\t};\n\n\treturn output;\n}
//requires jquery\n\n// input: an array of objects\n//\t\t a property that each of those object have\n// output: an array of the properties of all the objects\nwindow.skimObjectArray = function(objectArray, property){\n\tconsole.log("skimObjectArray(", "objectArray", objectArray, "property", property, ")")\n\tvar values = [];\n\n\tfor (var i = 0; i < objectArray.length; i++) {\n\t\tvar thingToAdd = objectArray[i][property];\n\t\tif(typeof thingToAdd === "object"){\n\t\t\t// i hope to god this works\n\t\t\tthingToAdd = objectArray[i][property].join("\sn")\n\t\t}\n\t\tvalues.push( thingToAdd );\n\t};\n\n\tvalues = values.join("\sn");\n\tvalues = values.split("\sn")\n\n\treturn values;\n}\n\nStory.prototype.appendCorpora = function(){\n\tvar corporaToAppend = tale.lookup("tags", "corpus");\n\tif(!corporaToAppend.length) return;\n\n\tfor(var i in corporaToAppend){\n\t\tvar currentPassage = corporaToAppend[i].title;\n\n\t\t// the rules are the concatenation of each symbol in this passage\n\t\tvar rules = [];\n\t\tvar lines = tale.passages[currentPassage].text.split("\sn")\n\t\tfor(var j in lines){\n\t\t\tvar line = lines[j];\n\t\t\tvar location = line.split("#");\n\t\t\tconsole.log("location: ", location);\n\t\t\tvar corpusLocation = location[0];\n\n\t\t\t// fetch me that sweet sweet boy\n\t\t\tvar corpus = $.ajax({\n\t\t\t\tdataType: "json",\n\t\t\t\turl: corpusLocation,\n\t\t\t\tasync: false\n\t\t\t});\n\t\t\tcorpus = corpus.responseJSON;\n\n\t\t\t// drill down to the array we want\n\t\t\tfor (var i = 1; i < location.length; i++) {\n\t\t\t\tconsole.log("corpus: ", corpus);\n\t\t\t\t// if there's a ! at the beginning of a location, skim the objArray for that property\n\t\t\t\tif(location[i][0] === "!"){\n\t\t\t\t\tcorpus = skimObjectArray(corpus, location[i].substring(1));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tcorpus = corpus[ location[i] ]\n\t\t\t};\n\n\t\t\tconsole.log("corpus: ", corpus);\n\t\t\t// add this into the symbol-in-progress\n\t\t\trules = rules.concat(corpus);\n\t\t\tconsole.log("rules: ", rules)\n\t\t}\n\n\t\t// the name of this symbol is the name of the passage\n\t\tvar finalJSON = "{ \s"" + currentPassage + "\s": " + JSON.stringify(rules) + " }";\n\n\t\t// save our dark deeds to the passage\n\t\ttale.passages[currentPassage].text = finalJSON;\n\n\t\t//tag this as JSON so it gets appended in the next step\n\t\ttale.passages[currentPassage].tags.push("JSON")\n\t}\n\n\tconsole.log("corpora loaded")\n}\n\nStory.prototype.appendJSON = function() {\n\tvar JSONtoAppend = tale.lookup("tags", "JSON");\n\tif(!JSONtoAppend.length) return;\n\n\tfor(i in JSONtoAppend){\n\t\tvar newJSON = JSON.parse(JSONtoAppend[i].text);\n\t\t$.extend(this.data, newJSON);\n\t}\n\tconsole.log("JSON appended");\n}\n\nfunction Story(){\n\tvar grammars = tale.lookup("tags", "grammar", "title");\n\tthis.data = {};\n\n\tvar links = /(\s[\s[\sb)(.+?)(\sb\s]\s])/g;\n\tvar sublinks = /([^\s[\s]]+)*(.+)/\n\n\tfunction convertSyntax(match, p1, p2, p3){\n\t\t// If a passage is invoked that's tagged as a grammar, change Twine links into Tracery symbols.\n\t\t// e.g.: [[animal]] => #animal#\n\t\t// e.g.: [[animal][capitalize]] => #animal.capitalize#\n\n\t\t// p1 is left brackets, p3 is right brackets\n\t\tvar targetLink = p2.split("][")[0];\n\t\tvar modifiers = p2.split("][").slice(1, p2.length).join(".");\n\t\tmodifiers = modifiers?("." + modifiers):"";\n\t\t\n\t\tvar trace = "#" + targetLink + modifiers + "#";\n\t\t\n\t\tvar linkIsGrammar = false;\n\t\tvar tags = tale.get(targetLink).tags\n\t\tfor(var i = 0; i < tags.length; i++){\n\t\t\tif(tags[i] == "grammar" || tags[i] == "corpus"){\n\t\t\t\tlinkIsGrammar = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn linkIsGrammar?trace:match;\n\t}\n\n\tfor(var i in grammars){\n\t\tif(grammars[i] == undefined) continue;\n\n\t\t// Passage names become grammar names, Passage text becomes grammar text. \n\t\tvar newSymbol = grammars[i].title\n\t\tvar newText = grammars[i].text\n\n\t\tvar link = /(\s[\s[\sb)(.+?)(\sb\s]\s])/g;\n\t\tnewText = newText.replace(link, convertSyntax);\n\t\t// Get everything that's being linked to.\n\n\t\tthis.data[newSymbol] = newText.split('\sn');\n\t}\n\n\tthis.appendCorpora();\n\tthis.appendJSON();\n\tconsole.log("Story: ", this);\n}\nStory.prototype.constructor = Story;\n\n// Append this to the tale object because I don't know where else to put it.\nTale.prototype.story = new Story();\n\nStory.prototype.toHTML = function() {\n\tvar output = [];\n\tvar tab = " ";\n\tvar beg = '\sn' + tab + "\s"<span class=\s"grammarContents\s">{{{"\n\tvar end = "}}}</span>\s""\n\n\tfor(var i in this.data){\n\t\tvar gram = "<span class=\s"grammarTitle\s">\s"" + i + "\s"</span>: [";\n\t\tgram += beg + this.data[i].join(end + ',' + beg) + end;\n\t\tgram += "]";\n\t\toutput.push(gram);\n\t}\n\treturn "{\sn" + output.join(",\sn") + "\sn}";\n}\n\nTale.prototype.JSONtoTwee = function() {\n\tvar JSONtoConvert = tale.lookup("tags", "JSON");\n\tvar combinedJSON = ""\n\n\tfor (var i in JSONtoConvert){\n\t\tcombinedJSON += JSONtoConvert[i].text;\n\t}\n\n\t// Note the {{{}}} delimiters in textPost. This is intended for display in Twine, so\n\t// if you're just running these raw they aren't necessary.\n\tvar regex = {titlesPre: /\st"(.+)": \s[/g, titlesPost: "<br>:: $1 [grammar]",\n\t\t\t\t textPre: /\st*"(.+)",*(?:\sn\st)?(?:\s],)*\sn/g, textPost: "{{{$1}}}<br>"}\n\n\tvar tweeOutput = combinedJSON.replace(regex.titlesPre, regex.titlesPost);\n\ttweeOutput = tweeOutput.replace(regex.textPre, regex.textPost);\n\ttweeOutput = tweeOutput.replace(/({\sn)|(]\sn})/g, "")\n\n\treturn tweeOutput;\n}
<<if !tale.grammar>>\n\t<<if tracery>>\n\t\t<<set tale.grammar = tracery.createGrammar(tale.story.data)>>\n\t\t<<print console.log("grammar: ", tale.grammar)>>\n\t<<else>>\n\t\t<<print console.log("grammar instantiation failed")>>\n\t<<endif>>\n<<endif>>
You have a secret fetish that only I know.\n\n[[Do you want to know?|run]]
// This is a slightly modified version of Leon Arnott's cyclinglink macro.\n\nversion.extensions.tracelinkMacro = {\n\tmajor: 0,\n\tminor: 1,\n\trevision: 0\n};\nmacros.tracelink = {\n\thandler: function(a, b, c) {\n\t\tvar rl = "traceLink";\n\n\t\tfunction toggleText(w) {\n\t\t\tw.classList.remove("traceLinkInit");\n\t\t\tw.classList.toggle(rl + "Enabled");\n\t\t\tw.classList.toggle(rl + "Disabled");\n\t\t\tw.style.display = ((w.style.display == "none") ? "inline" : "none")\n\t\t}\n\t\tswitch (c[c.length - 1]) {\n\t\t\tcase "end":\n\t\t\t\tvar end = true;\n\t\t\t\tc.pop();\n\t\t\t\tbreak;\n\t\t\tcase "out":\n\t\t\t\tvar out = true;\n\t\t\t\tc.pop();\n\t\t\t\tbreak\n\t\t}\n\t\tvar v = "";\n\t\tif (c.length && c[0][0] == "$") {\n\t\t\tv = c[0].slice(1);\n\t\t\tc.shift()\n\t\t}\n\t\tvar h = state.history[0].variables;\n\t\tif (out && h[v] === "") {\n\t\t\treturn\n\t\t}\n\t\tvar l = Wikifier.createInternalLink(a, null);\n\t\tl.className = "internalLink cyclingLink";\n\t\tl.setAttribute("data-cycle", 0);\n\n\t\t// Prebake a bunch of traces and use those as our links to cycle through.\n\t\tc = traceArray(c[0], 64);\n\n\t\tfor (var i = 0; i < c.length; i++) {\n\t\t\tvar on = (i == Math.max(c.indexOf(h[v]), 0));\n\t\t\tvar d = insertElement(null, "span", null, "traceLinkInit traceLink" + ((on) ? "En" : "Dis") + "abled");\n\t\t\tif (on) {\n\t\t\t\th[v] = c[i];\n\t\t\t\tl.setAttribute("data-cycle", i)\n\t\t\t} else {\n\t\t\t\td.style.display = "none"\n\t\t\t}\n\t\t\tinsertText(d, c[i]);\n\t\t\tif (on && end && i == c.length - 1) {\n\t\t\t\tl.parentNode.replaceChild(d, l)\n\t\t\t} else {\n\t\t\t\tl.appendChild(d)\n\t\t\t}\n\t\t}\n\t\tl.onclick = function() {\n\t\t\tvar t = this.childNodes;\n\t\t\tvar u = this.getAttribute("data-cycle") - 0;\n\t\t\tvar m = t.length;\n\t\t\ttoggleText(t[u]);\n\t\t\tu = (u + 1);\n\t\t\tif (!(out && u == m)) {\n\t\t\t\tu %= m;\n\t\t\t\tif (v) {\n\t\t\t\t\th[v] = c[u]\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\th[v] = ""\n\t\t\t}\n\t\t\tif ((end || out) && u == m - (end ? 1 : 0)) {\n\t\t\t\tif (end) {\n\t\t\t\t\tvar n = this.removeChild(t[u]);\n\t\t\t\t\tn.className = rl + "End";\n\t\t\t\t\tn.style.display = "inline";\n\t\t\t\t\tthis.parentNode.replaceChild(n, this)\n\t\t\t\t} else {\n\t\t\t\t\tthis.parentNode.removeChild(this);\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttoggleText(t[u]);\n\t\t\tthis.setAttribute("data-cycle", u)\n\t\t}\n\t}\n};
in the butt\n\t\tin a cemetary\n\t\ton the tarmac\n\t\twhile drinking soda\n\t\tin the face\n\t\tin SPACE\n\t\tat the doctor's office\n\t\twith my hair\n\t\tagainst my feet\n\t\tin the library\n\t\twhile on Facebook\n\t\tin the mouth\n\t\tunder the balls\n\t\tbetween the dicks\n\t\tin the armpit\n\t\tup the cunt\n\t\ton the underboob\n\t\tin a gorilla suit\n\t\twho I met on OKCupid\n\t\tin missionary position\n\t\tright after church\n\t\tright before church\n\t\twith a spreadsheet\n\t\twith a quartz dildo\n\t\tat raves\n\t\tat the gay pride parade\n\t\tduring work\n\t\twith peanut butter\n\t\twhile listening to a recording of myself\n\t\tinto a volcano\n\t\twho remind me of my grandmother\n\t\tin a swimming pool full of jello\n\t\twith boots on\n\t\ton top of old smokey\n\t\ton a bed of nails\n\t\twhile skydiving\n\t\twhile fully clothed\n\t\twhile stoned\n\t\twith a medium-sized cactus\n\t\tcovered in chocolate syrup\n\t\tand then being disgusted with myself\n\t\twhile wearing glasses\n\t\ttenderly\n\t\ton the sidewalk\n\t\tup the nose\n\t\ton the nipples\n\t\ton the neck\n\t\tbetween the toes\n\t\tdressed head to toe in leather\n\t\ton a beach\n\t\twithout them knowing\n\t\tbut not in a creepy way\n\t\twhile menstruating\n\t\twhile reading the dictionary out loud\n\t\twhile watching with a mirror\n\t\twhile on fire\n\t\twithout a condom\n\t\twith a boner\n\t\tin the early moonlight\n\t\t(*rimshot*)\n\t\tat band camp\n\t\tbehind the trailer park dumpster\n\t\twith an ice cube\n\t\tat the Renaissance fair\n\t\tunder the guise of night\n\t\tin a stranger's bed\n\t\tat the movie theater\n\t\tin a Turkish bath house\n\t\twhile wearing a dog collar\n\t\tin a cage\n\t\twhile pooping\n\t\ton all fours\n\t\tin the dressing room\n\t\twhile sipping bourbon beside the roaring fire\n\t\tat Burning Man\n\t\twho are begging for it\n\t\tin exchange for diamonds\n\t\ton the metal table in the morgue\n\t\tand then summoning Lucifer\n\t\ton a hospital gurney\n\t\twhile coated in aloe\n\t\tand stealing their fedoras\n\t\ton a swing\n\t\tin the back of a van\n\t\tbut I haven't done that since the eighties\n\t\ttomorrow\n\t\tand never calling them for a second date\n\t\twhile watching Twilight\n\t\twhile talking like Shakespeare characters\n\t\tusing a baby voice\n\t\tunder water\n\t\tafter a fight\n\t\tjust like that one scene in Caligula\n\t\tand then we make a card game about it\n\t\twith foam everywhere\n\t\twho is pregnant\n\t\tin a high school planetarium\n\t\tafter a storm\n\t\twhile walking the dog\n\t\twhile naked
html {\n width: 100%;\n\n /* Vertical colour gradient */\n background-image: linear-gradient(to bottom, black, midnightblue);\n background-image: -webkit-linear-gradient(top, black, midnightblue);\n background-attachment: fixed;\n\n /* Fallback colour */\n background-color: midnightblue;\n\n /* Vertical centering */\n height: 100%;\n display: table;\n}\nbody {\n /* Remove default styles */\n font-size: 100%;\n background-color: transparent;\n margin: 0;\n\n /* Vertical centering */\n height:100%;\n display:table-cell;\n vertical-align: middle;\n}\n#passages {\n border-left: 0px;\n margin: 0;\n /* Keep a gap at the top and bottom of the page,\n when the text is longer than the window's height. */\n padding: 5% 0;\n}\n\n.passage {\n /* Passage width */\n width: 60%;\n /* Horizontal centering */\n margin: 0 auto;\n\n /* Text formatting */\n color: white;\n font-size: 100%;\n text-align:center;\n}\n\n/* No sidebar */\n#sidebar {\n display:none;\n}\n\n/* Links */\na.internalLink, a.externalLink {\n color: #e300ff;\n\ttext-decoration:none;\n}\na.internalLink:hover, a.externalLink:hover {\n color: #b000ff;\n text-decoration: none;\n}\n\n/* Shrink the page when viewed on devices with a low screen width */\n@media screen and (max-width: 960px) {\n .passage { font-size: 90%; width: 70%; }\n}\n@media screen and (max-width: 840px) {\n .passage { font-size: 87.5%; width: 80%; }\n}\n@media screen and (max-width: 720px) {\n .passage { font-size: 75%; width: 90%; }\n}\n.revision-span-in {\n\topacity: 0;\n}\n.revision-span:not(.revision-span-out) {\n\ttransition: 1s; -webkit-transition: 1s;\n}\n.revision-span-out {\n\tposition:absolute;\n\topacity: 0;\n}
// Expands a symbol and returns the output.\nwindow.trace = function(symbol){\n\tif(symbol === undefined){\n\t\tsymbol = "origin";\n\t}\n\tif(tale.grammar === undefined){\n\t\tconsole.log("Couldn't find the grammar object.");\n\t\treturn "ERROR: Grammar object not found.";\n\t}\n\n\tvar output = tale.grammar.flatten("#" + symbol + "#")\t\n//\tconsole.log(symbol + " expands to:\sn" + output);\n\treturn output;\n}
[[verb]] [[noun]] [[flavor]]
[[I knew it.|run]]
v.2016-09-05
window.tracery = {\n utilities : {}\n};\n\n(function () {/**\n * @author Kate Compton\n */\n\nfunction inQuotes(s) {\n return '"' + s + '"';\n};\n\nfunction parseAction(action) {\n return action;\n};\n\n// tag format\n// a thing to expand, plus actions\n\nfunction parseTag(tag) {\n var errors = [];\n var prefxns = [];\n var postfxns = [];\n\n var lvl = 0;\n var start = 0;\n\n var inPre = true;\n\n var symbol,\n mods;\n\n function nonAction(end) {\n if (start !== end) {\n var section = tag.substring(start, end);\n if (!inPre) {\n errors.push("multiple possible expansion symbols in tag!" + tag);\n } else {\n inPre = false;\n var split = section.split(".");\n symbol = split[0];\n mods = split.slice(1, split.length);\n }\n\n }\n start = end;\n };\n\n for (var i = 0; i < tag.length; i++) {\n var c = tag.charAt(i);\n\n switch(c) {\n case '[':\n if (lvl === 0) {\n nonAction(i);\n }\n\n lvl++;\n break;\n case ']':\n lvl--;\n if (lvl === 0) {\n var section = tag.substring(start + 1, i);\n if (inPre)\n prefxns.push(parseAction(section));\n else\n postfxns.push(parseAction(section));\n start = i + 1;\n }\n break;\n\n default:\n if (lvl === 0) {\n\n }\n break;\n\n }\n }\n nonAction(i);\n\n if (lvl > 0) {\n var error = "Too many '[' in rule " + inQuotes(tag);\n errors.push(error);\n\n }\n\n if (lvl < 0) {\n var error = "Too many ']' in rule " + inQuotes(tag);\n errors.push(error);\n\n }\n\n return {\n preActions : prefxns,\n postActions : postfxns,\n symbol : symbol,\n mods : mods,\n raw : tag,\n errors : errors,\n };\n};\n\n// Split a rule into sections\nfunction parseRule(rule) {\n var sections = [];\n var errors = [];\n if (!( typeof rule == 'string' || rule instanceof String)) {\n errors.push("Cannot parse non-string rule " + rule);\n sections.errors = errors;\n return sections;\n }\n\n if (rule.length === 0) {\n return [];\n }\n\n var lvl = 0;\n var start = 0;\n var inTag = false;\n\n function createSection(end) {\n var section = rule.substring(start, end);\n if (section.length > 0) {\n if (inTag)\n sections.push(parseTag(section));\n else\n sections.push(section);\n }\n inTag = !inTag;\n start = end + 1;\n\n }\n\n for (var i = 0; i < rule.length; i++) {\n var c = rule.charAt(i);\n\n switch(c) {\n case '[':\n lvl++;\n break;\n case ']':\n lvl--;\n break;\n case '#':\n if (lvl === 0) {\n createSection(i);\n }\n break;\n default:\n break;\n\n }\n\n }\n\n if (lvl > 0) {\n var error = "Too many '[' in rule " + inQuotes(rule);\n errors.push(error);\n\n }\n\n if (lvl < 0) {\n var error = "Too many ']' in rule " + inQuotes(rule);\n errors.push(error);\n\n }\n\n if (inTag) {\n var error = "Odd number of '#' in rule " + inQuotes(rule);\n errors.push(error);\n }\n\n createSection(rule.length);\n sections.errors = errors;\n return sections;\n};\n\nfunction testParse(rule, shouldFail) {\n console.log("-------");\n console.log("Test parse rule: " + inQuotes(rule) + " " + shouldFail);\n var parsed = parseRule(rule);\n if (parsed.errors && parsed.errors.length > 0) {\n for (var i = 0; i < parsed.errors.length; i++) {\n console.log(parsed.errors[i]);\n }\n }\n \n\n}\n\nfunction testParseTag(tag, shouldFail) {\n console.log("-------");\n console.log("Test parse tag: " + inQuotes(tag) + " " + shouldFail);\n var parsed = parseTag(tag);\n if (parsed.errors && parsed.errors.length > 0) {\n for (var i = 0; i < parsed.errors.length; i++) {\n console.log(parsed.errors[i]);\n }\n }\n}\n\ntracery.testParse = testParse;\ntracery.testParseTag = testParseTag;\ntracery.parseRule = parseRule;\ntracery.parseTag = parseTag;\n\n\nfunction spacer(size) {\n var s = "";\n for (var i = 0; i < size * 3; i++) {\n s += " ";\n }\n return s;\n}\n\n/* Simple JavaScript Inheritance\n * By John Resig http://ejohn.org/\n * MIT Licensed.\n */\n\nfunction extend(destination, source) {\n for (var k in source) {\n if (source.hasOwnProperty(k)) {\n destination[k] = source[k];\n }\n }\n return destination;\n}\n\n// Inspired by base2 and Prototype\n(function() {\n var initializing = false,\n fnTest = /xyz/.test(function() { xyz;\n }) ? /\sb_super\sb/ : /.*/;\n\n // The base Class implementation (does nothing)\n this.Class = function() {\n };\n\n // Create a new Class that inherits from this class\n Class.extend = function(prop) {\n var _super = this.prototype;\n\n // Instantiate a base class (but only create the instance,\n // don't run the init constructor)\n initializing = true;\n var prototype = new this();\n initializing = false;\n\n // Copy the properties over onto the new prototype\n for (var name in prop) {\n // Check if we're overwriting an existing function\n prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn) {\n return function() {\n var tmp = this._super;\n\n // Add a new ._super() method that is the same method\n // but on the super-class\n this._super = _super[name];\n\n // The method only need to be bound temporarily, so we\n // remove it when we're done executing\n var ret = fn.apply(this, arguments);\n this._super = tmp;\n\n return ret;\n };\n })(name, prop[name]) : prop[name];\n }\n\n // The dummy class constructor\n function Class() {\n // All construction is actually done in the init method\n if (!initializing && this.init)\n this.init.apply(this, arguments);\n }\n\n // Populate our constructed prototype object\n Class.prototype = prototype;\n\n // Enforce the constructor to be what we expect\n Class.prototype.constructor = Class;\n\n // And make this class extendable\n Class.extend = arguments.callee;\n\n return Class;\n };\n})();\n\n/**\n * @author Kate\n */\n\nvar Rule = function(raw) {\n this.raw = raw;\n this.sections = parseRule(raw);\n\n};\n\nRule.prototype.getParsed = function() {\n if (!this.sections)\n this.sections = parseRule(raw);\n\n return this.sections;\n};\n\nRule.prototype.toString = function() {\n return this.raw;\n};\n\nRule.prototype.toJSONString = function() {\n return this.raw;\n};\n\n/**\n * @author Kate\n */\n\nvar RuleWeighting = Object.freeze({\n RED : 0,\n GREEN : 1,\n BLUE : 2\n});\n\nvar RuleSet = function(rules) {\n // is the rules obj an array? A RuleSet, or a string?\n if (rules.constructor === Array) {\n // make a copy\n rules = rules.slice(0, rules.length);\n } else if (rules.prototype === RuleSet) {\n // clone\n } else if ( typeof rules == 'string' || rules instanceof String) {\n var args = Array.prototype.slice.call(arguments);\n rules = args;\n } else {\n console.log(rules);\n throw ("creating ruleset with unknown object type!");\n }\n\n // create rules and their use counts\n\n this.rules = rules;\n this.parseAll();\n\n this.uses = [];\n this.startUses = [];\n this.totalUses = 0;\n for (var i = 0; i < this.rules.length; i++) {\n this.uses[i] = 0;\n this.startUses[i] = this.uses[i];\n this.totalUses += this.uses[i];\n }\n\n};\n\n//========================================================\n// Iterating over rules\n\nRuleSet.prototype.parseAll = function(fxn) {\n for (var i = 0; i < this.rules.length; i++) {\n if (this.rules[i].prototype !== Rule)\n this.rules[i] = new Rule(this.rules[i]);\n }\n\n};\n\n//========================================================\n// Iterating over rules\n\nRuleSet.prototype.mapRules = function(fxn) {\n return this.rules.map(function(rule, index) {\n return fxn(rule, index);\n });\n};\n\nRuleSet.prototype.applyToRules = function(fxn) {\n for (var i = 0; i < this.rules.length; i++) {\n fxn(this.rules[i], i);\n }\n};\n//========================================================\nRuleSet.prototype.get = function() {\n var index = this.getIndex();\n\n return this.rules[index];\n};\n\nRuleSet.prototype.getRandomIndex = function() {\n return Math.floor(this.uses.length * Math.random());\n};\n\nRuleSet.prototype.getIndex = function() {\n // Weighted distribution\n // Imagine a bar of length 1, how to divide the length\n // s.t. a random dist will result in the dist we want?\n\n var index = this.getRandomIndex();\n // What if the uses determine the chance of rerolling?\n\n var median = this.totalUses / this.uses.length;\n\n var count = 0;\n while (this.uses[index] > median && count < 20) {\n index = this.getRandomIndex();\n count++;\n }\n\n // reroll more likely if index is too much higher\n\n return index;\n};\n\nRuleSet.prototype.decayUses = function(pct) {\n this.totalUses = 0;\n for (var i = 0; i < this.uses; i++) {\n\n this.uses[index] *= 1 - pct;\n this.totalUses += this.uses[index];\n }\n};\n\nRuleSet.prototype.testRandom = function() {\n console.log("Test random");\n var counts = [];\n for (var i = 0; i < this.uses.length; i++) {\n counts[i] = 0;\n }\n\n var testCount = 10 * this.uses.length;\n for (var i = 0; i < testCount; i++) {\n\n var index = this.getIndex();\n this.uses[index] += 1;\n\n counts[index]++;\n this.decayUses(.1);\n }\n\n for (var i = 0; i < this.uses.length; i++) {\n console.log(i + ":\st" + counts[i] + " \st" + this.uses[i]);\n }\n};\n\nRuleSet.prototype.getSaveRules = function() {\n var jsonRules = this.rules.map(function(rule) {\n return rule.toJSONString();\n });\n\n return jsonRules;\n};\n\n/**\n * @author Kate Compton\n */\n\nvar Action = function(node, raw) {\n\n this.node = node;\n this.grammar = node.grammar;\n this.raw = raw;\n\n};\n\nAction.prototype.activate = function() {\n\n var node = this.node;\n node.actions.push(this);\n\n // replace any hashtags\n this.amended = this.grammar.flatten(this.raw);\n\n var parsed = parseTag(this.amended);\n var subActionRaw = parsed.preActions;\n if (subActionRaw && subActionRaw.length > 0) {\n this.subactions = subActionRaw.map(function(action) {\n return new Action(node, action);\n });\n\n }\n\n if (parsed.symbol) {\n var split = parsed.symbol.split(":");\n\n if (split.length === 2) {\n this.push = {\n symbol : split[0],\n\n // split into multiple rules\n rules : split[1].split(","),\n };\n // push\n node.grammar.pushRules(this.push.symbol, this.push.rules);\n\n } else\n throw ("Unknown action: " + parsed.symbol);\n }\n\n if (this.subactions) {\n for (var i = 0; i < this.subactions.length; i++) {\n this.subactions[i].activate();\n }\n }\n\n};\n\nAction.prototype.deactivate = function() {\n if (this.subactions) {\n for (var i = 0; i < this.subactions.length; i++) {\n this.subactions[i].deactivate();\n }\n }\n\n if (this.push) {\n this.node.grammar.popRules(this.push.symbol, this.push.rules);\n }\n};\n\n/**\n * @author Kate Compton\n */\n\nvar isConsonant = function(c) {\n c = c.toLowerCase();\n switch(c) {\n case 'a':\n return false;\n case 'e':\n return false;\n case 'i':\n return false;\n case 'o':\n return false;\n case 'u':\n return false;\n\n }\n return true;\n};\n\nfunction endsWithConY(s) {\n if (s.charAt(s.length - 1) === 'y') {\n return isConsonant(s.charAt(s.length - 2));\n }\n return false;\n};\n\nvar universalModifiers = {\n capitalizeAll : function(s) {\n return s.replace(/(?:^|\ss)\sS/g, function(a) {\n return a.toUpperCase();\n });\n\n },\n\n capitalize : function(s) {\n return s.charAt(0).toUpperCase() + s.slice(1);\n\n },\n\n inQuotes : function(s) {\n return '"' + s + '"';\n },\n\n comma : function(s) {\n var last = s.charAt(s.length - 1);\n if (last === ",")\n return s;\n if (last === ".")\n return s;\n if (last === "?")\n return s;\n if (last === "!")\n return s;\n return s + ",";\n },\n\n beeSpeak : function(s) {\n // s = s.replace("s", "zzz");\n\n s = s.replace(/s/, 'zzz');\n return s;\n },\n\n a : function(s) {\n if (!isConsonant(s.charAt()))\n return "an " + s;\n return "a " + s;\n\n },\n\n s : function(s) {\n\n var last = s.charAt(s.length - 1);\n\n switch(last) {\n case 'y':\n\n // rays, convoys\n if (!isConsonant(s.charAt(s.length - 2))) {\n return s + "s";\n }\n // harpies, cries\n else {\n return s.slice(0, s.length - 1) + "ies";\n }\n break;\n\n // oxen, boxen, foxen\n case 'x':\n return s.slice(0, s.length - 1) + "en";\n case 'z':\n return s.slice(0, s.length - 1) + "es";\n case 'h':\n return s.slice(0, s.length - 1) + "es";\n\n default:\n return s + "s";\n };\n\n },\n\n ed : function(s) {\n\n var index = s.indexOf(" ");\n var s = s;\n var rest = "";\n if (index > 0) {\n rest = s.substring(index, s.length);\n s = s.substring(0, index);\n\n }\n\n var last = s.charAt(s.length - 1);\n\n switch(last) {\n case 'y':\n\n // rays, convoys\n if (isConsonant(s.charAt(s.length - 2))) {\n return s.slice(0, s.length - 1) + "ied" + rest;\n\n }\n // harpies, cries\n else {\n return s + "ed" + rest;\n }\n break;\n case 'e':\n return s + "d" + rest;\n\n break;\n\n default:\n return s + "ed" + rest;\n };\n }\n};\n/**\n * @author Kate Compton\n */\n\n// A tracery expansion node\nvar nodeCount = 0;\n\nvar ExpansionNode = Class.extend({\n init : function() {\n this.depth = 0;\n this.id = nodeCount;\n nodeCount++;\n this.childText = "[[UNEXPANDED]]";\n },\n\n setParent : function(parent) {\n if (parent) {\n this.depth = parent.depth + 1;\n this.parent = parent;\n this.grammar = parent.grammar;\n }\n },\n\n expand : function() {\n // do nothing\n return "???";\n },\n\n expandChildren : function() {\n\n if (this.children) {\n this.childText = "";\n for (var i = 0; i < this.children.length; i++) {\n this.children[i].expand();\n this.childText += this.children[i].finalText;\n }\n this.finalText = this.childText;\n }\n\n },\n\n createChildrenFromSections : function(sections) {\n var root = this;\n this.children = sections.map(function(section) {\n\n if ( typeof section == 'string' || section instanceof String) {\n // Plaintext\n return new TextNode(root, section);\n } else {\n return new TagNode(root, section);\n }\n });\n }\n});\n\nvar RootNode = ExpansionNode.extend({\n init : function(grammar, rawRule) {\n this._super();\n this.grammar = grammar;\n this.parsedRule = parseRule(rawRule);\n },\n\n expand : function() {\n var root = this;\n this.createChildrenFromSections(this.parsedRule);\n\n // expand the children\n this.expandChildren();\n },\n});\n\nvar TagNode = ExpansionNode.extend({\n init : function(parent, parsedTag) {\n this._super();\n\n if (!(parsedTag !== null && typeof parsedTag === 'object')) {\n if ( typeof parsedTag == 'string' || parsedTag instanceof String) {\n console.warn("Can't make tagNode from unparsed string!");\n parsedTag = parseTag(parsedTag);\n\n } else {\n console.log("Unknown tagNode input: ", parsedTag);\n throw ("Can't make tagNode from strange tag!");\n\n }\n }\n\n this.setParent(parent);\n $.extend(this, parsedTag);\n },\n\n expand : function() {\n if (tracery.outputExpansionTrace)\n console.log(r.sections);\n\n this.rule = this.grammar.getRule(this.symbol);\n\n this.actions = [];\n\n // Parse the rule if it hasn't been already\n this.createChildrenFromSections(this.rule.getParsed());\n\n // Do any pre-expansion actions!\n for (var i = 0; i < this.preActions.length; i++) {\n var action = new Action(this, this.preActions[i]);\n action.activate();\n }\n\n // Map each child section to a node\n if (!this.rule.sections)\n console.log(this.rule);\n\n this.expandChildren();\n\n for (var i = 0; i < this.actions.length; i++) {\n\n this.actions[i].deactivate();\n }\n\n this.finalText = this.childText;\n for (var i = 0; i < this.mods.length; i++) {\n this.finalText = this.grammar.applyMod(this.mods[i], this.finalText);\n }\n\n },\n\n toLabel : function() {\n return this.symbol;\n },\n toString : function() {\n return "TagNode '" + this.symbol + "' mods:" + this.mods + ", preactions:" + this.preActions + ", postactions" + this.postActions;\n }\n});\n\nvar TextNode = ExpansionNode.extend({\n isLeaf : true,\n init : function(parent, text) {\n this._super();\n\n this.setParent(parent);\n\n this.text = text;\n\n this.finalText = text;\n },\n expand : function() {\n // do nothing\n },\n\n toLabel : function() {\n return this.text;\n }\n});\n\n/**\n * @author Kate Compton\n */\n\nfunction Symbol(grammar, key) {\n this.grammar = grammar;\n this.key = key;\n this.currentRules = undefined;\n this.ruleSets = [];\n\n};\n\nSymbol.prototype.loadFrom = function(rules) {\n\n rules = this.wrapRules(rules);\n this.baseRules = rules;\n\n this.ruleSets.push(rules);\n this.currentRules = this.ruleSets[this.ruleSets.length - 1];\n\n};\n\n//========================================================\n// Iterating over rules\n\nSymbol.prototype.mapRules = function(fxn) {\n\n return this.currentRules.mapRules(fxn);\n};\n\nSymbol.prototype.applyToRules = function(fxn) {\n this.currentRules.applyToRules(fxn);\n};\n\n//==================================================\n// Rule pushpops\nSymbol.prototype.wrapRules = function(rules) {\n if (rules.prototype !== RuleSet) {\n if (Array.isArray(rules)) {\n return new RuleSet(rules);\n } else if ( typeof rules == 'string' || rules instanceof String) {\n return new RuleSet(rules);\n } else {\n throw ("Unknown rules type: " + rules);\n }\n }\n // already a ruleset\n return rules;\n};\n\nSymbol.prototype.pushRules = function(rules) {\n rules = this.wrapRules(rules);\n this.ruleSets.push(rules);\n this.currentRules = this.ruleSets[this.ruleSets.length - 1];\n};\n\nSymbol.prototype.popRules = function() {\n var exRules = this.ruleSets.pop();\n\n if (this.ruleSets.length === 0) {\n //console.warn("No more rules for " + this + "!");\n }\n this.currentRules = this.ruleSets[this.ruleSets.length - 1];\n};\n\n// Clear everything and set the rules\nSymbol.prototype.setRules = function(rules) {\n\n rules = this.wrapRules(rules);\n this.ruleSets = [rules];\n this.currentRules = rules;\n\n};\n\nSymbol.prototype.addRule = function(rule) {\n this.currentRules.addRule(seed);\n};\n\n//========================================================\n// selection\n\nSymbol.prototype.select = function() {\n this.isSelected = true;\n\n};\n\nSymbol.prototype.deselect = function() {\n this.isSelected = false;\n};\n\n//==================================================\n// Getters\n\nSymbol.prototype.getRule = function(seed) {\n return this.currentRules.get(seed);\n};\n\n//==================================================\n\nSymbol.prototype.toString = function() {\n return this.key + ": " + this.currentRules + "(overlaying " + (this.ruleSets.length - 1) + ")";\n};\nSymbol.prototype.toJSON = function() {\n\n var rules = this.baseRules.rules.map(function(rule) {\n return '"' + rule.raw + '"';\n });\n return '"' + this.key + '"' + ": [" + rules.join(", ") + "]";\n};\n\nSymbol.prototype.toHTML = function(useSpans) {\n var keySpan = '"' + this.key + '"';\n if (useSpans)\n keySpan = "<span class='symbol symbol_" + this.key + "'>" + keySpan + "</span>";\n\n var rules = this.baseRules.rules.map(function(rule) {\n var s = '"' + rule.raw + '"';\n if (useSpans)\n s = "<span class='rule'>" + s + "</span>";\n return s;\n });\n return keySpan + ": [" + rules.join(", ") + "]";\n};\n\n/**\n * @author Kate Compton\n */\n\nfunction Grammar() {\n this.clear();\n};\n\nGrammar.prototype.clear = function() {\n // Symbol library\n this.symbols = {};\n \n this.errors = [];\n \n // Modifier library\n this.modifiers = {};\n\n // add the universal mods\n for (var mod in universalModifiers) {\n if (universalModifiers.hasOwnProperty(mod))\n this.modifiers[mod] = universalModifiers[mod];\n }\n};\n//========================================================\n// Loading\n\nGrammar.prototype.loadFrom = function(obj) {\n var symbolSrc;\n\n this.clear();\n\n if (obj.symbols !== undefined) {\n symbolSrc = obj.symbols;\n } else {\n symbolSrc = obj;\n }\n\n // get all json keys\n var keys = Object.keys(symbolSrc);\n\n this.symbolNames = [];\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n this.symbolNames.push(key);\n\n this.symbols[key] = new Symbol(this, key);\n this.symbols[key].loadFrom(symbolSrc[key]);\n }\n\n};\n\nGrammar.prototype.toHTML = function(useSpans) {\n // get all json keys\n var keys = Object.keys(this.symbols);\n\n this.symbolNames = [];\n\n var lines = [];\n\n var count = 0;\n for (var i = 0; i < keys.length; i++) {\n\n var key = keys[i];\n var symbol = this.symbols[key];\n\n if (symbol && symbol.baseRules) {\n\n lines.push(" " + this.symbols[key].toHTML(useSpans));\n\n }\n };\n\n var s;\n s = lines.join(",</p><p>");\n s = "{<p>" + s + "</p>}";\n return s;\n};\n\nGrammar.prototype.toJSON = function() {\n // get all json keys\n var keys = Object.keys(this.symbols);\n\n this.symbolNames = [];\n\n var lines = [];\n\n var count = 0;\n for (var i = 0; i < keys.length; i++) {\n\n var key = keys[i];\n var symbol = this.symbols[key];\n\n if (symbol && symbol.baseRules) {\n\n lines.push(" " + this.symbols[key].toJSON());\n\n }\n };\n\n var s;\n s = lines.join(",\sn");\n s = "{\sn" + s + "\sn}";\n return s;\n};\n\n//========================================================\n// selection\n\nGrammar.prototype.select = function() {\n this.isSelected = true;\n};\n\nGrammar.prototype.deselect = function() {\n this.isSelected = false;\n};\n\n//========================================================\n// Iterating over symbols\n\nGrammar.prototype.mapSymbols = function(fxn) {\n var symbols = this.symbols;\n return this.symbolNames.map(function(name) {\n return fxn(symbols[name], name);\n });\n};\n\nGrammar.prototype.applyToSymbols = function(fxn) {\n for (var i = 0; i < this.symbolNames.length; i++) {\n var key = this.symbolNames[i];\n fxn(this.symbols[key], key);\n }\n};\n\n//========================================================\nGrammar.prototype.addOrGetSymbol = function(key) {\n if (this.symbols[key] === undefined)\n this.symbols[key] = new Symbol(key);\n\n return this.symbols[key];\n};\n\nGrammar.prototype.pushRules = function(key, rules) {\n var symbol = this.addOrGetSymbol(key);\n symbol.pushRules(rules);\n};\n\nGrammar.prototype.popRules = function(key, rules) {\n var symbol = this.addOrGetSymbol(key);\n var popped = symbol.popRules();\n\n if (symbol.ruleSets.length === 0) {\n // remove symbol\n this.symbols[key] = undefined;\n }\n};\n\nGrammar.prototype.applyMod = function(modName, text) {\n if (!this.modifiers[modName]) {\n console.log(this.modifiers);\n throw ("Unknown mod: " + modName);\n }\n return this.modifiers[modName](text);\n};\n\n//============================================================\nGrammar.prototype.getRule = function(key, seed) {\n var symbol = this.symbols[key];\n if (symbol === undefined) {\n var r = new Rule("{{" + key + "}}");\n\n r.error = "Missing symbol " + key;\n return r;\n }\n\n var rule = symbol.getRule();\n if (rule === undefined) {\n var r = new Rule("[" + key + "]");\n console.log(r.sections);\n r.error = "Symbol " + key + " has no rule";\n return r;\n }\n\n return rule;\n};\n\n//============================================================\n// Expansions\nGrammar.prototype.expand = function(raw) {\n\n // Start a new tree\n var root = new RootNode(this, raw);\n\n root.expand();\n\n return root;\n};\n\nGrammar.prototype.flatten = function(raw) {\n\n // Start a new tree\n var root = new RootNode(this, raw);\n\n root.expand();\n\n return root.childText;\n};\n\n//===============\n\nGrammar.prototype.analyze = function() {\n this.symbolNames = [];\n for (var name in this.symbols) {\n if (this.symbols.hasOwnProperty(name)) {\n this.symbolNames.push(name);\n }\n }\n\n // parse every rule\n\n for (var i = 0; i < this.symbolNames.length; i++) {\n var key = this.symbolNames[i];\n var symbol = this.symbols[key];\n // parse all\n for (var j = 0; j < symbol.baseRules.length; j++) {\n var rule = symbol.baseRules[j];\n rule.parsed = tracery.parse(rule.raw);\n // console.log(rule);\n\n }\n }\n\n};\n\nGrammar.prototype.selectSymbol = function(key) {\n console.log(this);\n var symbol = this.get(key);\n};\n/**\n * @author Kate Compton\n\n */\n\ntracery.createGrammar = function(obj) {\n var grammar = new Grammar();\n grammar.loadFrom(obj);\n return grammar;\n};\n\ntracery.test = function() {\n\n console.log("==========================================");\n console.log("test tracery");\n\n // good\n tracery.testParse("", false);\n tracery.testParse("fooo", false);\n tracery.testParse("####", false);\n tracery.testParse("#[]#[]##", false);\n tracery.testParse("#someSymbol# and #someOtherSymbol#", false);\n tracery.testParse("#someOtherSymbol.cap.pluralize#", false);\n tracery.testParse("#[#do some things#]symbol.mod[someotherthings[and a function]]#", false);\n tracery.testParse("#[fxn][fxn][fxn[subfxn]]symbol[[fxn]]#", false);\n tracery.testParse("#[fxn][#fxn#][fxn[#subfxn#]]symbol[[fxn]]#", false);\n tracery.testParse("#hero# ate some #color# #animal.s#", false);\n tracery.testParseTag("[action]symbol.mod1.mod2[postAction]", false);\n\n // bad\n tracery.testParse("#someSymbol# and #someOtherSymbol", true);\n tracery.testParse("#[fxn][fxn][fxn[subfxn]]symbol[fxn]]#", true);\n\n // bad\n tracery.testParseTag("stuff[action]symbol.mod1.mod2[postAction]", true);\n tracery.testParseTag("[action]symbol.mod1.mod2[postAction]stuff", true);\n\n tracery.testParse("#hero# ate some #color# #animal.s#", true);\n tracery.testParse("#[#setPronouns#][#setOccupation#][hero:#name#]story#", true);\n\n};\n \n})();
<<trace>>\n\n<<timedreplace 2s >> \n<<becomes>>Hey, that's fine. I wonder if there are [[any more|more]]<<endtimedreplace>>
jquery:on\nhash:off\nbookmark:on\nmodernizr:off\nundo:on\nobfuscate:off\nexitprompt:off\nblankcss:off\n
<<silently>>\nUses the parameter if one was passed. Then, checks for the $symbol variable. If neither is present, uses "origin". Clears $symbol at the end.\n\n<<if parameter(0)>>\n\t<<set $symbol to parameter(0)>>\n<<else>><<if $symbol>>\n\tNo need to do anything.\n<<else>>\n\t<<set $symbol to "origin">>\n<<endif>><<endif>>\n\n<<endsilently>><<print console.log("trace " + $symbol)>><<print tale.grammar.flatten("#" + $symbol + "#")>><<forget $symbol>>
String.prototype.contains = function(substring){\n\tif (substring.constructor === Array){\n\t\tfor (var i = 0; i < substring.length; i++){\n\t\t\tif(this.contains(substring[i])){\n\t\t\t\treturn substring[i]; // Non-empty string evaluates to true\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t} else {\n\t\treturn this.indexOf(substring) > 0;\n\t}\n}
// Returns a new version of a given expansion.\nwindow.retrace = function(symbol, old, maxAttempts){\n\tif(maxAttempts === undefined){\n\t\tmaxAttempts = 32;\n\t}\n\tif(!(maxAttempts > 1)){\n\t\tmaxAttempts = 1;\n\t}\n\t\n\tvar output = "", attempts = 0;\n\tdo{\n\t\toutput = trace(symbol);\n\t\tattempts++;\n\t}while(output == old && attempts < maxAttempts)\n\n//\tconsole.log("retrace:"\n//\t\t\t\t+ "\sn\stold: " + old\n//\t\t\t\t+ "\sn\stnew: " + output\n//\t\t\t\t+ "\sn\stattempts: " + attempts)\n\treturn output;\n}
Dominating\nFisting\n\t\tFucking\n\t\tForgetting\n\t\tFingering\n\t\tGoing down on\n\t\tStimulating\n\t\tSynergizing with\n\t\tBlowing\n\t\tSexing\n\t\tHaving intercourse with\n\t\tSubmitting to\n\t\tWhipping\n\t\tSpanking\n\t\tDressing up as\n\t\tKnowing (in the Biblical way)\n\t\tLaughing at\n\t\tTickling\n\t\tHandcuffing\n\t\tAnnoying\n\t\tPeeing on\n\t\tVideotaping\n\t\tUrinating on\n\t\tPenis fencing with\n\t\tDisplaying\n\t\tMounting\n\t\tUtilizing\n\t\tPitching\n\t\tCatching\n\t\tCarpet munching\n\t\tBeing abducted by\n\t\tBeing gangbanged by\n\t\tBeing probed by\n\t\tProbing\n\t\tJizzing all over\n\t\tPenetrating\n\t\tGroping\n\t\tCutting\n\t\tJerking off to\n\t\tTying up\n\t\tSniffing\n\t\tBeing peed on by\n\t\tSqueezing\n\t\tArguing with\n\t\tPretending to be\n\t\tShowering with\n\t\tYelling at\n\t\tWatching\n\t\tBeing vomited on by\n\t\tVomiting on\n\t\tFemale ejaculation by\n\t\tEating\n\t\tBeing naked with\n\t\tThrusting into\n\t\tScissoring\n\t\tCuddling with\n\t\tGalvinizing\n\t\tSinging to\n\t\tFiguratively sleeping with\n\t\tLiterally sleeping with\n\t\tOrgies with\n\t\tRimming\n\t\tSeducing\n\t\tFornicating with\n\t\tDry humping\n\t\tMassaging\n\t\tLubing up\n\t\tSodomizing\n\t\tSixty-nining\n\t\tCaressing\n\t\tSauteeing\n\t\tBabysitting\n\t\tFarting at\n\t\tMenstruating on\n\t\tWorking out with\n\t\tDeflowering\n\t\tFacebook stalking\n\t\tBiting\n\t\tQueefing under\n\t\tStroking\n\t\tRiding\n\t\tDefecating on\n\t\tDoing drugs with\n\t\tDiscussing politics with\n\t\tFlossing after\n\t\tNot being able to even with\n\t\tFrolicking with\n\t\tStarting a sex cult with\n\t\tProcrastinating with\n\t\tRectally examaning\n\t\tMoaning at the sight of\n\t\tLending my old team jacket to\n\t\tCollecting\n\t\tDrinking fine wine with\n\t\tPlaying pretend with\n\t\tFighting\n\t\tGetting hit by\n\t\tStomping on\n\t\tDreaming about\n\t\tSmothering
(function(){version.extensions.replaceMacrosCombined={major:1,minor:1,revision:7};var nullobj={handler:function(){}};function showVer(n,notrans){if(!n){return;}n.innerHTML="";\nnew Wikifier(n,n.tweecode);n.setAttribute("data-enabled","true");n.style.display="inline";n.classList.remove("revision-span-out");if(!notrans){n.classList.add("revision-span-in");\nif(n.timeout){clearTimeout(n.timeout);}n.timeout=setTimeout(function(){n.classList.remove("revision-span-in");n=null;},20);}}function hideVer(n,notrans){if(!n){return;\n}n.setAttribute("data-enabled","false");n.classList.remove("revision-span-in");if(n.timeout){clearTimeout(n.timeout);}if(!notrans){n.classList.add("revision-span-out");\nn.timeout=setTimeout(function(){if(n.getAttribute("data-enabled")=="false"){n.classList.remove("revision-span-out");n.style.display="none";n.innerHTML="";}n=null;\n},1000);}else{n.style.display="none";n.innerHTML="";n=null;}}function tagcontents(b,starttags,desttags,endtags,k){var l=0,c="",tg,a,i;function tagfound(i,e,endtag){for(var j=0;\nj<e.length;j++){if(a.indexOf("<<"+e[j]+(endtag?">>":""),i)==i){return e[j];}}}a=b.source.slice(k);for(i=0;i<a.length;i++){if(tg=tagfound(i,starttags)){l++;}else{if((tg=tagfound(i,desttags,true))&&l==0){b.nextMatch=k+i+tg.length+4;\nreturn[c,tg];}else{if(tg=tagfound(i,endtags,true)){l--;if(l<0){return null;}}}}c+=a.charAt(i);}return null;}var begintags=[];var endtags=[];function revisionSpanHandler(g,e,f,b){var k=b.source.indexOf(">>",b.matchStart)+2,vsns=[],vtype=e,flen=f.length,becomes,c,cn,m,h,vsn;\nfunction mkspan(vtype){h=insertElement(m,"span",null,"revision-span "+vtype);h.setAttribute("data-enabled",false);h.style.display="none";h.tweecode="";return h;}if(this.shorthand&&flen){while(f.length>0){vsns.push([f.shift(),(this.flavour=="insert"?"gains":"becomes")]);\n}}else{if(this.flavour=="insert"||(this.flavour=="continue"&&this.trigger=="time")){vsns.push(["","becomes"]);}}if(this.flavour=="continue"&&flen){b.nextMatch=k+b.source.slice(k).length;\nvsns.push([b.source.slice(k),vtype]);}else{becomes=["becomes","gains"];c=tagcontents(b,begintags,becomes.concat(endtags),endtags,k);if(c&&endtags.indexOf(c[1])==-1){while(c){vsns.push(c);\nc=tagcontents(b,begintags,becomes,endtags,b.nextMatch);}c=tagcontents(b,begintags,["end"+e],endtags,b.nextMatch);}if(!c){throwError(g,"can't find matching end"+e);\nreturn;}vsns.push(c);if(this.flavour=="continue"){k=b.nextMatch;b.nextMatch=k+b.source.slice(k).length;vsns.push([b.source.slice(k),""]);}}if(this.flavour=="remove"){vsns.push(["","becomes"]);\n}cn=0;m=insertElement(g,"span",null,e);m.setAttribute("data-flavour",this.flavour);h=mkspan("initial");vsn=vsns.shift();h.tweecode=vsn[0];showVer(h,true);while(vsns.length>0){if(vsn){vtype=vsn[1];\n}vsn=vsns.shift();h=mkspan(vtype);h.tweecode=vsn[0];}if(typeof this.setup=="function"){this.setup(m,g,f);}}function quantity(m){return(m.children.length-1)+(m.getAttribute("data-flavour")=="remove");\n}function revisionSetup(m,g,f){m.className+=" "+f[0].replace(" ","_");}function keySetup(m,g,f){var key=f[0];m.setEventListener("keydown",function l(e){var done=!revise("revise",m);\nif(done){m.removeEventListener("keydown",l);}});}function timeSetup(m,g,f){function cssTimeUnit(s){if(typeof s=="string"){if(s.slice(-2).toLowerCase()=="ms"){return Number(s.slice(0,-2))||0;\n}else{if(s.slice(-1).toLowerCase()=="s"){return Number(s.slice(0,-1))*1000||0;}}}throwError(g,s+" isn't a CSS time unit");return 0;}var tm=cssTimeUnit(f[0]);var s=state.history[0].passage.title;\nsetTimeout(function timefn(){if(state.history[0].passage.title==s){var done=!revise("revise",m);if(!done){setTimeout(timefn,tm);}}},tm);}function hoverSetup(m){var fn,noMouseEnter=(document.head.onmouseenter!==null),m1=m.children[0],m2=m.children[1],gains=m2.className.indexOf("gains")>-1;\nif(!m1||!m2){return;}m1.onmouseenter=function(e){var efp=document.elementFromPoint(e.clientX,e.clientY);while(efp&&efp!==this){efp=efp.parentNode;}if(!efp){return;\n}if(this.getAttribute("data-enabled")!="false"){revise("revise",this.parentNode);}};m2.onmouseleave=function(e){var efp=document.elementFromPoint(e.clientX,e.clientY);\nwhile(efp&&efp!==this){efp=efp.parentNode;}if(efp){return;}if(this.getAttribute("data-enabled")!="false"){revise("revert",this.parentNode);}};if(gains){m1.onmouseleave=m2.onmouseleave;\n}if(noMouseEnter){fn=function(n){return function(e){if(!event.relatedTarget||(event.relatedTarget!=this&&!(this.compareDocumentPosition(event.relatedTarget)&Node.DOCUMENT_POSITION_CONTAINED_BY))){this[n]();\n}};};m1.onmouseover=fn("onmouseenter");m2.onmouseout=fn("onmouseleave");if(gains){m1.onmouseout=m2.onmouseout;}}m=null;}function mouseSetup(m){var evt=(document.head.onmouseenter===null?"onmouseenter":"onmouseover");\nm[evt]=function(){var done=!revise("revise",this);if(done){this[evt]=null;}};m=null;}function linkSetup(m,g,f){var l=Wikifier.createInternalLink(),p=m.parentNode;\nl.className="internalLink replaceLink";p.insertBefore(l,m);l.insertBefore(m,null);l.onclick=function(){var p,done=false;if(m&&m.parentNode==this){done=!revise("revise",m);\nscrollWindowTo(m);}if(done){this.parentNode.insertBefore(m,this);this.parentNode.removeChild(this);}};l=null;}function visitedSetup(m,g,f){var i,done,shv=state.history[0].variables,os="once seen",d=(m.firstChild&&(this.flavour=="insert"?m.firstChild.nextSibling:m.firstChild).tweecode);\nshv[os]=shv[os]||{};if(d&&!shv[os].hasOwnProperty(d)){shv[os][d]=1;}else{for(i=shv[os][d];i>0&&!done;i--){done=!revise("revise",m,true);}if(shv[os].hasOwnProperty(d)){shv[os][d]+=1;\n}}}[{name:"insert",flavour:"insert",trigger:"link",setup:linkSetup},{name:"timedinsert",flavour:"insert",trigger:"time",setup:timeSetup},{name:"insertion",flavour:"insert",trigger:"revisemacro",setup:revisionSetup},{name:"later",flavour:"insert",trigger:"visited",setup:visitedSetup},{name:"keyinsert",flavour:"insert",trigger:"key",setup:keySetup},{name:"replace",flavour:"replace",trigger:"link",setup:linkSetup},{name:"timedreplace",flavour:"replace",trigger:"time",setup:timeSetup},{name:"mousereplace",flavour:"replace",trigger:"mouse",setup:mouseSetup},{name:"hoverreplace",flavour:"replace",trigger:"hover",setup:hoverSetup},{name:"revision",flavour:"replace",trigger:"revisemacro",setup:revisionSetup},{name:"keyreplace",flavour:"replace",trigger:"key",setup:keySetup},{name:"timedremove",flavour:"remove",trigger:"time",setup:timeSetup},{name:"mouseremove",flavour:"remove",trigger:"mouse",setup:mouseSetup},{name:"hoverremove",flavour:"remove",trigger:"hover",setup:hoverSetup},{name:"removal",flavour:"remove",trigger:"revisemacro",setup:revisionSetup},{name:"once",flavour:"remove",trigger:"visited",setup:visitedSetup},{name:"keyremove",flavour:"remove",trigger:"key",setup:keySetup},{name:"continue",flavour:"continue",trigger:"link",setup:linkSetup},{name:"timedcontinue",flavour:"continue",trigger:"time",setup:timeSetup},{name:"mousecontinue",flavour:"continue",trigger:"mouse",setup:mouseSetup},{name:"keycontinue",flavour:"continue",trigger:"key",setup:keySetup},{name:"cycle",flavour:"cycle",trigger:"revisemacro",setup:revisionSetup},{name:"mousecycle",flavour:"cycle",trigger:"mouse",setup:mouseSetup},{name:"timedcycle",flavour:"cycle",trigger:"time",setup:timeSetup},{name:"keycycle",flavour:"replace",trigger:"key",setup:keySetup}].forEach(function(e){e.handler=revisionSpanHandler;\ne.shorthand=(["link","mouse","hover"].indexOf(e.trigger)>-1);macros[e.name]=e;macros["end"+e.name]=nullobj;begintags.push(e.name);endtags.push("end"+e.name);});function insideDepartingSpan(elem){var r=elem.parentNode;\nwhile(!r.classList.contains("passage")){if(r.classList.contains("revision-span-out")){return true;}r=r.parentNode;}}function reviseAll(rt,rname){var rall=document.querySelectorAll(".passage [data-flavour]."+rname),ret=false;\nfor(var i=0;i<rall.length;i++){if(!insideDepartingSpan(rall[i])){ret=revise(rt,rall[i])||ret;}}return ret;}function revise(rt,r,notrans){var ind2,curr,next,ind=-1,rev=(rt=="revert"),rnd=(rt.indexOf("random")>-1),fl=r.getAttribute("data-flavour"),rc=r.childNodes,cyc=(fl=="cycle"),rcl=rc.length-1;\nfunction doToGainerSpans(n,fn){for(var k=n-1;k>=0;k--){if(rc[k+1].classList.contains("gains")){fn(rc[k],notrans);}else{break;}}}for(var k=0;k<=rcl;k++){if(rc[k].getAttribute("data-enabled")=="true"){ind=k;\n}}if(rev){ind-=1;}curr=(ind>=0?rc[ind]:(cyc?rc[rcl]:null));ind2=ind;if(rnd){ind2=(ind+(Math.floor(Math.random()*rcl)))%rcl;}next=((ind2<rcl)?rc[ind2+1]:(cyc?rc[0]:null));\nvar docurr=(rev?showVer:hideVer);var donext=(rev?hideVer:showVer);var currfn=function(){if(!(next&&next.classList.contains("gains"))||rnd){docurr(curr,notrans);doToGainerSpans(ind,docurr,notrans);\n}};var nextfn=function(){donext(next,notrans);if(rnd){doToGainerSpans(ind2+1,donext,notrans);}};if(!rev){currfn();nextfn();}else{nextfn();currfn();}return(cyc?true:(rev?(ind>0):(ind2<rcl-1)));\n}macros.revert=macros.revise=macros.randomise=macros.randomize={handler:function(a,b,c){var l,rev,rname;function disableLink(l){l.style.display="none";}function enableLink(l){l.style.display="inline";\n}function updateLink(l){if(l.className.indexOf("random")>-1){enableLink(l);return;}var rall=document.querySelectorAll(".passage [data-flavour]."+rname),cannext,canprev,i,ind,r,fl;\nfor(i=0;i<rall.length;i++){r=rall[i],fl=r.getAttribute("data-flavour");if(insideDepartingSpan(r)){continue;}if(fl=="cycle"){cannext=canprev=true;}else{if(r.firstChild.getAttribute("data-enabled")==!1+""){canprev=true;\n}if(r.lastChild.getAttribute("data-enabled")==!1+""){cannext=true;}}}var can=(l.classList.contains("revert")?canprev:cannext);(can?enableLink:disableLink)(l);}function toggleText(w){w.classList.toggle(rl+"Enabled");\nw.classList.toggle(rl+"Disabled");w.style.display=((w.style.display=="none")?"inline":"none");}var rl="reviseLink";if(c.length<2){throwError(a,b+" macro needs 2 parameters");\nreturn;}rname=c.shift().replace(" ","_");l=Wikifier.createInternalLink(a,null);l.className="internalLink "+rl+" "+rl+"_"+rname+" "+b;var v="";var end=false;var out=false;\nif(c.length>1&&c[0][0]=="$"){v=c[0].slice(1);c.shift();}switch(c[c.length-1]){case"end":end=true;c.pop();break;case"out":out=true;c.pop();break;}var h=state.history[0].variables;\nfor(var i=0;i<c.length;i++){var on=(i==Math.max(c.indexOf(h[v]),0));var d=insertElement(null,"span",null,rl+((on)?"En":"Dis")+"abled");if(on){h[v]=c[i];l.setAttribute("data-cycle",i);\n}else{d.style.display="none";}insertText(d,c[i]);l.appendChild(d);}l.onclick=function(){reviseAll(b,rname);var t=this.childNodes,u=this.getAttribute("data-cycle")-0,m=t.length,n,lall,i;\nif((end||out)&&u>=m-(end?2:1)){if(end){n=this.removeChild(t[u+1]||t[u]);n.className=rl+"End";n.style.display="inline";this.parentNode.replaceChild(n,this);}else{this.parentNode.removeChild(this);\nreturn;}}else{toggleText(t[u]);u=(u+1)%m;if(v){h[v]=c[u];}toggleText(t[u]);this.setAttribute("data-cycle",u);}lall=document.getElementsByClassName(rl+"_"+rname);\nfor(i=0;i<lall.length;i++){updateLink(lall[i]);}};disableLink(l);setTimeout((function(l){return function(){updateLink(l);};}(l)),1);l=null;}};macros.mouserevise=macros.hoverrevise={handler:function(a,b,c,d){var endtags=["end"+b],evt=(window.onmouseenter===null?"onmouseenter":"onmouseover"),t=tagcontents(d,[b],endtags,endtags,d.source.indexOf(">>",d.matchStart)+2);\nif(t){var rname=c[0].replace(" ","_"),h=insertElement(a,"span",null,"hoverrevise hoverrevise_"+rname),f=function(){var done=!reviseAll("revise",rname);if(b!="hoverrevise"&&done){this[evt]=null;\n}};new Wikifier(h,t[0]);if(b=="hoverrevise"){h.onmouseover=f;h.onmouseout=function(){reviseAll("revert",rname);};}else{h[evt]=f;}h=null;}}};macros.instantrevise={handler:function(a,b,c,d){reviseAll("revise",c[0].replace(" ","_"));\n}};macros.endmouserevise=nullobj;macros.endhoverrevise=nullobj;}());
Your Secret Fetish
ostriches\n\t\tbooks\n\t\tMitt Romney\n\t\tmy computer\n\t\tsomeone's hair\n\t\ta pale immitation of Carl Sagan\n\t\tGod\n\t\tvery tiny things\n\t\tspicy ramen noodles\n\t\ta poster of Richard Simmons\n\t\tplants\n\t\ttentacles\n\t\tcats\n\t\tfurries\n\t\tan English literature professor\n\t\tclowns\n\t\tfurniture\n\t\tmannequins\n\t\tbros\n\t\taliens\n\t\tbald women\n\t\tthe elderly\n\t\tMilo Something\n\t\tnuns\n\t\tlibrarians\n\t\tthe entire Blue Man Group\n\t\tfirefighters\n\t\tandrogynous bodybuilders\n\t\tpolice officers\n\t\tpostal workers\n\t\toxen\n\t\tmermaids\n\t\tCthulhu\n\t\tgoth chicks\n\t\tSuperman\n\t\tgenderqueer people\n\t\ttriangles\n\t\tcyberpunks\n\t\tphallic vegetables\n\t\tguitarists\n\t\ta David Bowie impersonator\n\t\tguitars\n\t\tlightbulbs\n\t\tbears (in the gay way)\n\t\tbears (in the mammal way)\n\t\tbestselling authors\n\t\ttypewriters\n\t\tcactuses\n\t\tglass\n\t\tsoldiers\n\t\texotic dancers\n\t\tfood\n\t\tneedles\n\t\tblood\n\t\tpoliticians\n\t\tstewardesses\n\t\tred heads\n\t\tbellybuttons\n\t\tshoes\n\t\tpeanut butter\n\t\tlatex gloves\n\t\tconjoined twins\n\t\tlizards\n\t\tchocolate\n\t\tfreshly butchered meat\n\t\tdental dams\n\t\tprostitutes\n\t\tundulating midsections\n\t\tpimps\n\t\tbiceps\n\t\tnipples\n\t\tperky tits\n\t\tgoats\n\t\tmarzipan\n\t\tpsychics\n\t\tswords\n\t\tcakes\n\t\tinsects\n\t\tcold hard cash\n\t\tpriests\n\t\tmy ex\n\t\tpubes\n\t\tunicorns\n\t\tlips\n\t\tathletes\n\t\tconvicts\n\t\tdevil worshippers\n\t\tmetal heads\n\t\tcyborgs\n\t\thipsters\n\t\trobots\n\t\ttoads\n\t\tNeck Face\n\t\tvampires\n\t\tclunky old cellphones\n\t\tliterally any ancient trickster god\n\t\tslash fiction writers\n\t\tpeople with derpy smiles \n\t\tfire eaters \n\t\tthick thick sausages
<<traceryInit>>
window.grammar = function(rule){\n\treturn tale.get(rule).text.split('\sn');\n}
Hyacinth Nil