event code

So, code. Specifically, the encounter and scene code: How are events written? What do they look like? What code structures are in play?

Maybe let's start with a short summary of THE STATE OF THE ART, before getting into the HELL GAME system:

The method people have grown to expect for games like this is a PARSER. This is the method both CoC & TiTS use (and a bunch of others) and they're kind of the established trend-setters. This is a setup where writers write scenes in plain text, with occasional parser sequences, and then have an entirely separate coder person link all the scenes together into actual code.

So, TiTS has [pc.cockBiggest], which (according to their docs) is a sequence that will generate a prose chunk like "dick" or "pre-oozing, arm-sized tentacle-cock" that applies to the biggest dick applicable to the current scene. you'd expect to see this in a scene used something like "she grabs your [pc.cockBiggest]", right. This saves time having to manually branch on dick count and size and type every single time you want to refer to a dick.

But this gets more complicated and has some limitations. [pc.vagina] describes the pc's vagina, sure, but you can have more than one, so it also takes a count: [pc.vagina 0], [pc.vagina 1], etc. So in practice, in the code, you end up seeing stuff that's basically like

x = figure_out_the_cock_to_use_here()
...
output ("blah blah scene text [pc.cock " + x + "] etc more text");

Other issues include singular/plural grammar checks ("your cock" vs. "your cocks"), or conditional inclusions ("your balls", but only if you 1. have balls that 2. are external), both of which don't have parser sequences. The official stance is "mark the sections and the coder will handle it when they code up the scene". In actual TiTS code, this ends up looking like:

output("your heads. Cradling your " + pc.buttDescript() + ", Celise arrests your stumbles with nothing more than her own cushiony body. Her aqueous tendrils touch every part of you: your [pc.legs], the underside of your [pc.belly], ");
if(pc.balls > 0) output("your [pc.sack], ");

or

output("\n\nCelise surges back over you and begins to caress your sore ");
if(pc.balls == 0) output("loins");
else output("[pc.balls]");
output("\n\nCelise smiles and reduces the suction, cutting off the stream of [pc.cum] a moment before the cylindrical cock-traps start to lurch up and down, back and forth, jacking you off with hot, liquid weight. Your pumped-up, over-sized cock");
if(pc.cockTotal() > 1) output("s engorge");
else output(" engorges");

I.e., There's a general problem here with the logic needed for a scene escaping the limits of what a parser can do. The parser doesn't allow for branching, so any branches need to be determined in code and output needs to stop and then resume after the branch.

Fall of Eden, which also uses a parser, just selectively adds parser sequences at runtime:

var real = !p1cock.isStrapon;
var knotted = p1cock.Knot();
...
parse["c"] = real ? "cock" : "strap-on";
parse["knot"] = knotted ? ", swallowing the swell of your knot as if it were nothing" : "";
Text.Add("With that, she lifts herself up and impales herself on you in one smooth motion, sinking down onto your [c] and letting it slip inside her with ease, her folds parting wetly to admit you[knot].", parse);

which solves certain flexibility problems, though that still requires dropping out of the pure parser into the realm of real code, but at least lets you do it in bulk in advance, instead of all over the place.

These examples are all fairly small branches. There are large-scale branches too: "are the correct game switches active for this scene to trigger" is too complex for a parser setup to handle, and it's not really clear how that could even work when dealing with something that's designed to only handle string output.

IMO parsers are useful:

There are limits to what situations a parser can provide for without exploding into an entire sublanguage -- and if you go that far, you've basically just shifted the burden of coding onto the writers anyway, only now instead of having them code in actionscript or javascript or whatever they're coding in your homemade, bespoke parser language, so it's not really clear if all the work making the parser helped at all. A parser solves some problems, but it doesn't and can't categorically remove all the problems inherent in writing large amounts of content. Ultimately, somebody has to write some code, and that code is always going to be kinda complex.

A parser is mostly there to make things easier on writers, not really coders. Coding an entire parser and debugging it is a lot of work! And it's work that is dealing with code shit -- precedence and tokenizers and lexers and state-machine bugs -- rather than work that's, like, making content for your game. Which is fine if you have coders to do the code shit and have writers who wouldn't know a boolean if it bit them, but since I'm the sole coder and writer for HELL GAME that's not a very useful way to separate things. I have writing skills and coding skills, so writing up a whole parser just for my own use would be... not a great use of time, I think. I also have some stylistic goals that make a parser less useful; I'm explicitly interested in making HELL GAME less madlibby, which means I actively don't want certain parser fragments to exist (e.g., [skin] for skin/fur/feathers/scales; in HELL GAME when skin type comes up there are usually explicit branches with substantially different outputs, rather than depending on a single "he cums across yr [skin]" line)

So, now it's time to talk about my code.


The HELL GAME events are written in the source. this is EFFECTIVELY the same as CoC or TiTS events -- all the game logic is in code regardless -- with the only major difference being that CoC & TiTS are in actionscript and HELL GAME is in Haskell. But if you know your languages, you know that's... a pretty big difference. I could basically also say HELL GAME events are written in a parser that happens to run in Haskell itself; Haskell has a lot more flexibility in terms of letting the programmer create new syntax and logic structures, which means I'm not stuck doing if/else branches and string concatenation the same way somebody using actionscript or javascript is.

(As an aside, the scenes are executed on the server side. When a player activates an event, there's a minimal JSON api that fires off from the game, sending the pc's body data and the encounter's state data to the server, which processes it and then returns a big data chunk representing the encounter flowchart, which the game runs through based on the player's choices. The game runs like this because the other option is having all the events and event data written in javascript, and as difficult as writing some of these events can get in haskell, it would be a hundred times worse in javascript. The main drawback is that this means I have to RECOMPILE THE SERVER every time I make a game update.

But consequently I'm not directly calling an 'output' function in the event code, and due to the JSON nature of this interface, events have a 'canonical' parsed format that is just a big chunk of data; this means I could fairly easily add in some things that are much more difficult to do in a more direct framework, like scene tags or decision flowcharts, just by adding a few things into the parsed data.)


So in HELL GAME, on the player side, you have your body tree. Internally, this is parsed into a somewhat more coherent data package -- a BodyGlob -- that stores things like your basic body shape (biped, centaur, naga, etc), limb counts, limb covering data for all major limbs (fur, skin, scales, etc), and of course dick count, shape, size, and material. As well as a bunch of other stuff. The events are functions that take the BodyGlob and the monster's body (generally a much simpler data chunk that only has a few, or no, toggles), and then output a scene chunk. Generating an entire encounter flowchart involves starting with a seed scene (the introduction) and flowing through all the branches, ultimately returning all the reachable scenes indexed by internal scene name.

(This is incidentally why encounters error out instantly if there's a problem, rather than letting you get halfway through to the actual problem -- I put it together so that if there's an error anywhere in the scene flowchart, the entire thing errors, in the philosophy that 1. errors like that should just not be happening period, so it's important to catch them when they happen and 2. loud errors are easier to fix. I wasn't really anticipating adding in like three extra bonus bodytypes that aren't supported anywhere, but I guess that's hindsight for you.)

So what does HELL GAME encounter code actually look like? WELL HERE'S A BIG EXAMPLE:

fuckIntroReal :: MarkedScene Index Vars FlameDemon
fuckIntroReal b f =
	[ dialog f $ "Oh hey."
		/ Paragraph / "Actually you could really do me a solid here if you wanna,"
	, Narration2 $ "he says as he stands up."
		/ case clothes f of
			Naked -> "Your gaze immediately drops to his crotch: formerly nestled in the shadow of his lap is an enormous sheath, his pendulous balls swaying beneath as he shifts his weight. Coarse black hair spreads all across his inner thighs, creeping up his stomach, and in the center, in sharp relief, is his oversized cock."
			Robe -> "He shrugs off the loop of robe across his shoulder and tugs open the cord around his waist. He's wearing something like black compression shorts underneath, stretchy fabric hugely distended over a massive bulge. He hooks his thumbs into the waistband and tugs the fabric down, and his sheath -- goatlike and massive -- all but falls out, his equally-huge balls lolling out sluggishly a half-second later. His balls sway back and forth, audibly smacking his thighs. His thighs and lean stomach are covered in coarse black hair, framing the titanic weight of his still-soft, still-sheathed cock."
		/ "His flesh churns, flesh of his sac twitching, sheath fattening until it's wider than one of his wrists."
	, dialog f $ "So it's kind of awkward actually, like -- man, you don't know what it's like having an animal dick hooked up to you. It's so distracting, man."
		/ Paragraph / "So I kinda, uh... I kinda cursed my dick. So I couldn't touch it. So I'd stop jerking off when I needed to do spell diagramming."
		/ Paragraph / "But that sure as hell didn't stop me from" / em "wanting" / ", and now-- Ffuck, I need to get off, please."
	, Narration2 $ "He reaches down to touch his sheath, swollen now, but his hands glide off when he brings them close, like there's a cocoon a few inches thicker than his cock wrapped around it, deflecting his hands. He groans, half-frustrated and half-aroused, breath coming in sharp pants."
		/ Paragraph / "He's got goat parts, and so he's got a goat cock. Nevertheless, it's still a little surprising when the first thing out of his sheath looks like a big rubbery worm, attached to the tip of his dick. His actual cockhead comes to a point, but the flesh around his slit bulges outward -- not slightly, but by a full few inches, becoming a thick cord of spongy flesh jutting out past his cockhead; his pizzle." --  <-- first time only
		/ "His cock twitches, and a gush of pre erupts from the end of his pizzle, fluid dynamics sending the rubbery flesh lashing first in one direction and then the other, spraying his pre absolutely everywhere."
		/ Paragraph / "He's gasping, now, stomach trembling from the effort to keep his cock sheathed even for the rest of this conversation, and even that's failing, as he slowly unsheathes, pink goat dick spilling out and out, muscles fighting it every inch of the way."
	, dialog f $
		"It's a little like meditation, y'know? It clears your mind until you're thinking about only one thing. And it keeps you there. Not thinking about anything else."
	, Narration
		[ "His cock bobs in the air, a continual ooze of pre spilling from his pizzle down across his lean stomach. Then his cock jerks, a solid spray of slime splattering up his stomach and chest, and he groans, eyes fluttering shut."
		]
	, dialog f $ "It's -- it's pretty distracting. You gotta --"
	, Narration
		[ "He's breathing hard, stomach swelling and hollowing, each breath sending his cock unsheathing further."
		]
	, dialog f $ "You gotta help me out. Anything, fuck, it feels so good, but you gotta -- I gotta come!"
	, Narration
		[ "He's fully hard now, huffing, drooling, and it looks like his cock is in charge: its immense weight budding off from his body, each lurch dragging him forward."
		, "Fully hard, it spans from his crotch to his neck, bending slowly under its own weight. His shaft is easily thicker than his own trim biceps; it's thicker than his hocks even. He could fit both hands around it easily, sure, but it's certainly also long enough he could just suck himself off; it looks like he really does want some assistance here."
		, "He's humping the air, thighs gripping his sheath and stroking it back and forth when he bows his hips down; that much is allowed apparently, but it doesn't look like that much is gonna get him off, it'll only keep him plastering himself in gushes of pre."
		]
	, dialog f $ "Fuck, do whatever you want, just get me off," / em "please" / "!"
	, Choices $ catMaybes
		[ guardC (hasArms b) ("jerk him off", JerkOff)
		, guardC (hasMouth b) ("blow him", Blow)
		, case locoplan b of
			Basic x
				| x `elem` [Biped, Naga, Slithering] -> Just ("sit on his dick", SitAnal)
				| x `elem` [Centaur, Quadruped] -> Just ("let him mount you", MountAnal)
			_ -> Nothing
		, pure ("nah", Reject)
		]
	]

There are a few things going on here. I'll skip parsing the Haskell for you, assuming that you already know Haskell or don't really care about the details. But basically this is a list of actions, the main ones being Narrations, and ending with a Choices. Inside them are a few branches, based on the flame demon type or the PC's body. "Narration" is scene narration, obviously, and there are various other structures (not pictured) to set up challenges, give/take items for the PC, present choices, or make shops, etc etc. This one event isn't particularly complicated, and doesn't really branch on the PC's body at all except at the very end, where it checks which sex scene options are available to the PC based on some of their body properties.

Here's a slightly more in-depth scene:

jerkOff b f =
	[ Narration2 $ Paragraph
		/ case locoplan b of
			Basic Centaur -> "You take a step in, folding your legs under you, and reach out and touch his dick."
			Basic Naga -> "You slither closer, and reach out and touch his dick."
			Basic Biped -> "You reach out and touch his dick."
			f -> bodyFail JerkOff f
		/ "It shudders in your" / hand / ", a thick burble of pre spurting an inch from the tip and splattering down, but that's nothing compared to the full-body shudder the flame demon makes, mouth open in a feral cry. He starts humping instantly, hands clamped around your" / partAdjective Arms / "forearm, keening wildly."
		/ Paragraph / "You wrap both" / hands / "around his cock, giving him a tunnel, already slick and sloppy with his own pre, to fuck. He arches his entire body up, hips jerking off the ground, the wet" / em "slop-slop-slop" / "of his thrusts loud. His shaft's gristly under your" / partAdjective Arms / "palms, flesh slick and rubbery, lumps and bulges down the mammoth length of his cock. You start stroking, active participant instead of simply giving him a touch to use, and he keens again, lurching up into your thrusts, the sloppy, flooded flesh of his sheath grinding against your" / hands / "before he snaps back, dragging most of his cock back down as you stroke upwards to the tip, thumbs digging into the rim of his cockhead," / fingers / "sliding across his bulbous tip, capturing his squirming, lashing pizzle; his rubbery flesh bloating minutely under your touch as you dam the flow of pre even for a second."
		/ Paragraph / "His chest heaves, stomach hollowing until you can see his ribs clearly, head thrown back, eyes closed, mouth open, whining and bleating as you stroke him off. His cock is a pillar standing straight up in the air, throbbing and pulsing, slinging pre in every direction. You keep stroking steadily, his thrusts ragged, halting, body lurching to the side with the force of his upward thrusts."
		/ Paragraph / "His entire body shudders, his gasps stopping for a brief moment in a rattle, and his fingers dig down hard against your forearms. His cock shudders, muscles across his trim stomach spasming, lurching his cock left and right, and then he lets out a desperate bleat. His cock erupts like a fountain, tremors running up the length until a mess of silver-grey come erupts out, a sloppy cord making zigzags in the air from the lashing of his pizzle. You bring one" / hand / "up higher, working your thumb over the rim of his cockhead, and he sobs, bleating and groaning, as his cock kicks again, second blast hosing out even with the first volley still in the air, again, and again, and again. Come sprays all across your bodies,"
		/ case bodyMat_ Chest b of
			Solid (FMat _ Scales) -> "sheening your scales,"
			Solid (FMat _ Fur) -> mempty
			_ -> mempty
		/ "and comes down across him with heavy, meaty" / em "splats" / ", soaking his fur to his skin and then entirely burying it"
		/ case bodyMat_ Chest b of
			Solid (FMat _ Fur) -> ", your fur smearing with his, just as saturated"
			_ -> mempty
		/ ". His cock pulses in your" / hand / "over and over as he unleashes his pent-up load, writhing on the come-covered floor."
		/ Paragraph / "It has to be a minute before he stops, each spurt now just an upwelling of thick ooze, streaming down the glazed length of his shaft, your" / hands / "only a lump under the inch-thick coating of sluggishly-flowing come. You peel your" / hands / "away and he lets out a soft sigh, huge cords of come stretching between you as his cock wobbles and then crashes down across his chest like a falling tree, sending out a swampy wave of come when it hits with a" / em "smack" / ", cock shuddering now with the flame demon's gasping breath, rising and falling with his chest."
		/ Paragraph / "He swallows, open mouth flooded with come, and wipes his messy face with an equally messy hand, gulping again, muscles across his stomach and hips still spasmodically twitching."
	] <> closerDialog b f

So that maybe gives you a bit of an idea what I'm working with here.

(Some terminology: bodyFail is the function that generates those error messages you see when you end up with an unsupported body in a scene; mempty is haskell-ese for "nothing"; and _ in a pattern match means "anything; we don't care")

There are a few parser-esque chunks here: hand, hands, fingers, and the like are fairly simple replacement functions: you get "hand" or "paw" or "claw" or whatever, as applicable. There are a bunch of them, and they're mostly for situations when there's some minor specificity about the PC's body that it would be super tedious to try to manually write every time. Are they touching you on the sides or on the flanks, that kind of thing. (There's also one called groan, which is based on the species of your head. humans groan, goats bleat, bulls low, snakes hiss, etc.) I tend to write these as necessary and chuck them into a common file for general use.

That partAdjective function mostly returns absolutely nothing currently, but the GOAL is to have some build (or material, or some-notable-characteristic) notes there.

You might notice that there isn't any spacing logic there: there's things like "hits with a" / em "smack" / ", cock shuddering" where you absolutely want a space added between "a" and "smack", but really don't want a space added between "smack" and ",". this is because when I first wrote up these scenes, I did have to properly leave leading/trailing spaces, and to specially denote commas (and other punctuation), and I missed so many that somebody sent me a bug report that was basically nothing but pages of "these two words are conjoined" or "there's a space here between the word and the comma/period", and I realized I reallyyyyy had to do something to categorically fix that kind of mistake or else it would be happening everywhere, forever. So now... basically that / function does it, by adding in spaces or not as required, and I can just never think about leading/trailing spaces and it'll still work perfectly.

This is a minor thing, but it's a good example of identifying a class of bugs that are super tedious to fix and can be automatically solved, and then automatically solving them, so that I never again have to spend dev time fixing spacing issues. On a similar "reducing tedium of coding these scenes up" note, I have another function that can automatically pluralize verbs and nouns based on the count of a pc's bodyparts (it's called 's', and gets used below once, in "cock"^s; other scenes use it more often).

Likewise, when putting together scenes and scene indexes one of my concerns was wanting to avoid a situation where I could fuck up and typo something and end up with an incoherent scene. This is actually one of the places Haskell works really well as a language; one of its strength is its typing system -- in the first code snippet above there's a type signature:

fuckIntroReal :: MarkedScene Index Vars FlameDemon
where MarkedScene is defined in my scene utilities file:
type MarkedScene i vars mob = BodyGlob -> mob -> [Event i vars]
which basically means "a MarkedScene is a function that takes the pc body, as well as a specific monster body, and returns a list of Events that are indexed by i and use vars for variable storage". So for example all the flame demon scenes take the FlameDemon monster body, and end up having access to whatever random values that specific one has set. The i there is filled by Index, which is a local type that basically lists every scene in the scene index:
data Index
	= OpeningOptions | TalkOpening | Talk Subject | ShopPrompt | Leave
	| FuckIntro | JerkOff | Blow | SitAnal | MountAnal
	| Reject
	| Bye | Uncurse
	deriving (Eq, Ord, Show)
and you can see some of those in the choice branch above.

The point of all of this is that if I forget to write a scene, or typo the name of a scene label, or something like that, I don't end up with players after-the-fact going "hey this scene freezes halfway through and says it can't find "MpuntAnal"", I end up with a compile error immediately that says "hey you made a typo" or "hey you never actually put a MountAnal scene in here". This also insulates me a little from the grit of the event framework: all I have to say is that there's a choice with a given name and a given scene to jump to, and there's underlying code that translates that into the actual prompts players get, without making me have to manually assemble UI buttons or whatever. These are all individually minor things, but it means there's a whole set of low-level tedious bugs that just don't happen, that I don't have to spend time really thinking about or trying to catch because the system catches them for me.

(I haven't used variables much (they're still a work in progress, and they can't yet do some necessary things wrt changing event states, so I haven't used them much) but they follow the same pattern; if I typo one or forget to specify that, yeah, dryads store a "looking for a farm" flag, then the compiler complains and tells me precisely what I did wrong. I also have to specifically name global flags, as distinct from local flags -- every scene can only look at its own flags and the global flags, so it's not possible to accidentally clobber flags by using the same name or index or whatever in two different scenes. Once I add in rewriting monster event data, that'll work in the same fashion: it won't actually be possible for a scene to rewrite an encounter into an incoherent state.)

So that's all very useful when it comes to keeping up with these code files that are thousands of lines long.

(Personally, I think a large part of being a programmer is being lazy and tedium-adverse enough that you automate everything that can be automated. It's also about being wrong and bad at programming enough that you find ways to make it impossible to make as many mistakes as you can, and when you can't to make your mistakes loud and impossible to quietly fall through the cracks, so that you can catch them before other people end up dealing with them. The worst bug I've had so far is... uh a complex one involving Haskell formatting and precedence rules that ended up meaning that sometimes huge chunks out of the middle of scenes would vanish with absolutely no warning. So far my solution to that has been "don't use the thing that makes that happen", but that's exactly the kind of problem this framework is structured to avoid. And that, generally, it's pretty good at!)


So anyway here's what an actual sex scene looks like: (this one specifically is limited to bipeds / nagas / snakes, since quadrupeds and centaurs get an entirely-separate being-mounted scene)

sitAnal b f =
	[ Narration2 $ do
		Paragraph / case locoplan b of
			Basic Biped -> "You stand over him "
			_ -> "You slither up before him "
		/ "-- his cock, standing nearly straight up in the air, smears slick pre across "
		/ case locoplan b of
			Basic Biped -> "your" / partAdjective Legs / "legs, cockhead tapping against your" / partAdjective Ass / "ass cheeks"
			Basic Naga -> "your lower body, "
				/ case bodySpecies Tail b of
					Just x -> "the underbelly of your" / animalName x / "half"
					Nothing -> c "all over your wormlike underbelly"
			Basic Slithering -> "the"
				/ case bodyMat_ Tail b of
					Solid (FMat _ Protoplasm) -> "rubbery, protoplasmic"
					_ -> mempty
				/ "underside of your body; thick cords of it drool down"
				/ case bodyMat_ Tail b of
					Solid (FMat _ Protoplasm) -> mempty
					Solid (FMat _ x) -> "your" / matword x
					_ -> c "your tail"
				/ "all the way to the ground"
			f -> bodyFail SitAnal f
		/ "."
		/ Paragraph / case locoplan b of
			Basic Biped -> "His hands wrap around"
				/ case bodySpecies Legs b of -- this should just be a partAdjective call
					Just Goat -> c "your goatish ankles"
					_ -> "your" / ankles
				/ ", clenching, and his cock twitches in counterpoint, juddering in the air, "
				/ case bodyMat_ (Waist Hind) b of
					Solid (FMat _ Skin) -> c "slapping with wet smacks against your skin"
					Solid (FMat _ x) | x `elem` [Fur, Coat] -> "grinding wetly through your" / matword x / "and soaking it into a trench"
					Solid (FMat _ Scales) -> c "slapping against your side and sliding the wrong way up your scales"
					Solid (FMat _ Protoplasm) -> c "slapping and digging into your soft body"
					Trans (FMat _ Skin) (FMat _ Fur) -> c "smearing back and forth over the line on your hips where your fur grows in"
					_ -> c "smacking against you"
				/ "until you reach back and guide it into place, sliding between your cheeks to tap against your hole. The flame demon groans, his gush of pre squirting out of your cleft and"
				/ case bodyMat_ Legs b of
					Solid (FMat _ Skin) -> "smearing down your thighs"
					Solid (FMat _ Fur) -> "soaking the fur of your thighs"
					Solid (FMat _ Coat) -> "trickling through your coat"
					_ -> "drooling down your thighs"
				/ Period
			_ -> "His hands wrap around the meat of your body, "
				/ case bodyMat_ Chest b of
					Solid (FMat _ Scales) -> "digging into your scales, "
					_ -> mempty
				/ "and his cock twitches in counterpoint, juddering against your underbelly, "
				/ when (hasDick b) ("rutting up and down just below your" / unsheathed / "cock"^s / ", cockhead dragging against "
					/ (hasCloaca ? "your swollen cloaca" ?: "the cleft of your asshole")
					/ ". The flame demon groans, his gush of pre squirting out of your hole and smearing down your underbelly.")
		/ Paragraph / "You bear down, "
		/ when (locoplan b == Basic Biped) (c "squatting slightly,")
		/ case locoplan b of
			Basic x | x `elem` [Biped, Naga] -> "hand keeping his huge, wobbling cock in place as it slowly breaches your hole,"
			_ -> "coils wrapping around his huge, wobbling cock to keep it in place as it slowly breaches your hole,"
		/ "cockhead slipping in with shocking ease. It's thick, heavy, shuddering with his heartbeat; each burst of pre sloshes inside you before oozing out, streaming down his shaft. The flame demon bleats, hips jerking up, and the first few inches of his cock jerk back and forth inside you, lewd slurping noises coming from your" / (hasNagaCloaca ? "cloaca" ?: "ass") / "as he humps away. "
		/ Paragraph / (hasLocotype Biped ? "You squat lower," ?: "You sink down further,")
			/ "cock driving deeper inside, the flame demon's erratic thrusts sending it crashing back and forth against your inner walls"
			/ when (hasProstate b) (c ", glancing impacts against your prostate making you groan")
			/ "."
			/ case locoplan b of
				Basic Biped -> "The flame demon claws higher, hands sliding up your calves, rolling over your knees -- and then when he reaches your thighs, slightly angled, "
				Basic Naga -> "The flame demon grabs your hips, hands sliding over the junction where your scales turn to skin, rubbing up and down for a moment before"
				Basic Slithering -> "The flame demon grabs your coils, hands curving around the huge twists of your body, sliding between your tangled body before"
				f -> bodyFail SitAnal f
			/ "his entire body seizes in a" / em "yank" / ", dragging you down as he thrusts up, sending you plunging down on his cock, driving all the rest of it, all the way down to the sheath, deep into your"
			/ (hasNagaCloaca ? "cloaca" ?: "ass") / "in a single brutal motion that knocks the breath from your lungs"
			/ case locoplan b of
				Basic Biped -> "and nearly knocks you to the ground"
				_ -> mempty
			/ "."
		/ Paragraph
		/ hasLocotype Biped ? "You roll forward, on your knees straddling him," ?: "You slump down "
		/ "and catch your breath, his cock a huge writhing" / em "thing" / "inside you, lurching and writhing; the flame demon squirms weakly on the ground, bleating softly as his hips jerk up randomly, clawing at your" / hips / ". After a moment you start riding his cock, "
		/ (hasLocotype Biped ? "squatting up and down," ?: "coils shifting all across his lap,")
		/ "half his sloppy length slurping from your"
		/ (hasNagaCloaca ? "cloaca" ?: "ass") / ", streaming with pre, before you fall and take it down to the root, "
		/ (hasNagaCloaca ? "hole" ?: "ass") / "hitting the flame demon's crotch with a wet" / em "smack" / "that gets wetter each time you do it. The flame demon groans, hips jerking up to meet you, cannonball nuts "
		/ hasLocotype Biped
			? ("flopping just high enough to smack against your cheeks"
				/ case bodyMat_ Legs b of
					Solid (FMat _ Fur) -> ", sodden, soaking weight smearing messy rinds of pre all over your fur"
					_ -> ", smearing pre all over your ass"
				/ ".")
			 ?: "slapping against your twined coils."
		/ Paragraph / "The flame demon's chest heaves, stomach hollowing until you can see his ribs clearly, head thrown back, eyes closed, mouth open, whining and bleating as you ride his cock. His cock is a pillar, cockhead ramming deep inside you, jarring your heartbeat, knocking the breath from your lungs, your guts flooded with pre, weight sloshing inside you with each "
		/ case locoplan b of
			Basic Biped -> "squat"
			Basic Naga -> "slump downward"
			Basic Slithering -> "coil"
			f -> bodyFail SitAnal f
		/ ". You keep riding him steadily, his thrusts ragged, halting, body lurching to the side with the force of his upward thrusts."
		/ Paragraph / "The flame demon bleats loud, hunching faster, and drives the final few inches of his cock back and forth, cockhead stirring up thick currents in the slimy mass of pre building up in your gut. His entire body shudders, abs contracting, cock lurching left and right nearly strong enough to send you swaying with it, and then the entire thing goes rigid, muscles spasming and making it flare a fraction thicker, spasms traveling from base to tip, every inch of it felt inside you, until finally his first shot of come erupts like a firehose."
		/ Paragraph / "He shoots again, and again, and again, not a second between each pulse, your stomach gurgling and straining from the sudden weight, sloshing and slopping inside you, loud enough to be heard outside. The flame demon just groans, sharp little bleats punctuating each gush, balls jerking up to kick against your"
		/ hasLocotype Biped ? "ass cheeks" ?: "underbelly"
		/ "as he unloads inside you, sheath jammed up flush against your spread hole, stretching wider with each throb of his cock."
		/ Paragraph / "By the time he's spent himself, your gut is swollen and sloshing, a steady gush of silver-grey come pouring from your "
		/ hasNagaCloaca ? "cloaca" ?: "ass"
		/ "around his shaft. You slide forward, an inch of his cock pulling out, and slowly "
		/ hasLocotype Slithering ? "slide off" ?: "rise up"
		/ ", his cock all but spilling from your "
		/ hasNagaCloaca ? "hole" ?: "ass"
		/ ", half-hard and coated to dripping with his load, more and more flooding from around his shaft, until the head erupts with a soggy" / em "pop" / "and a waterfall of come. His shaft wobbles in the air for a moment before it crashes down across his chest, splattering come in every direction."
	] <> closerDialog b f

Of course, all of this is still majorly a work in process. When I started and wrote up the initial events, the code was... much different in a lot of ways. Hell, when I first made the game live I didn't even have formatting codes, so all the em uses above were just _underscores_ raw in the game text. It's been a process of writing more events and learning how to streamline this process that's gotten me to this point, and there are still a lot of weird sticking points I'm thinking about how to resolve. But this is the state of the HELL GAME code as of now. Hopefully this was an interesting and informative read!