from __future__ import annotations import random import re from typing import Any def _lettered(prefix: str, count: int) -> list[str]: letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" return [f"{prefix.capitalize()} {letters[index]}" for index in range(max(0, count))] def _pick_distinct(rng: random.Random, items: list[str], count: int) -> list[str]: if not items: return [] if len(items) >= count: return rng.sample(items, count) picked = list(items) while len(picked) < count: picked.append(items[rng.randrange(len(items))]) return picked def _participant_context(women_count: int, men_count: int) -> dict[str, list[str]]: women = _lettered("woman", women_count) men = _lettered("man", men_count) return {"women": women, "men": men, "people": women + men} def build_hardcore_role_graph( rng: random.Random, subcategory: dict[str, Any], context: dict[str, Any], item_axis_values: dict[str, Any] | None = None, pov_labels: list[str] | None = None, ) -> str: if context.get("subject_type") != "configured_cast": return "" women_count = int(context.get("women_count") or 0) men_count = int(context.get("men_count") or 0) people_count = women_count + men_count if people_count <= 0: return "" participants = _participant_context(women_count, men_count) women = participants["women"] men = participants["men"] people = participants["people"] slug = str(subcategory.get("slug") or subcategory.get("name") or "").lower() item_text = " ".join((item_axis_values or {}).values()).lower() pov_set = set(pov_labels or []) def any_person(exclude: set[str] | None = None) -> str: exclude = exclude or set() pool = [person for person in people if person not in exclude] or people return rng.choice(pool) def any_woman(exclude: set[str] | None = None) -> str: exclude = exclude or set() pool = [person for person in women if person not in exclude] or [person for person in people if person not in exclude] or people return rng.choice(pool) def any_man(exclude: set[str] | None = None) -> str: exclude = exclude or set() pool = [person for person in men if person not in exclude] or [person for person in people if person not in exclude] or people return rng.choice(pool) def support_sentence(exclude: set[str]) -> str: extras = [person for person in people if person not in exclude] if not extras: return "" extra = rng.choice(extras) actions = [ "kisses and grips the nearest body", "holds hips open for the camera", "touches breasts, thighs, and stomach", "keeps one hand on a partner's ass", "watches close and joins the body contact", "presses in from the side with hands on skin", ] return f" {extra} {rng.choice(actions)}." def foreplay_position_graph(primary: str, partner: str) -> str: text = " ".join( str(part or "").lower() for part in ( item_text, *((item_axis_values or {}).values()), ) ) if any(term in text for term in ("undressing", "removing clothing", "removing clothes", "pulling clothing", "sliding straps", "unbuttoning")): return ( f"{primary} and {partner} stand close while {partner}'s hands pull clothing aside from {primary}'s body; " f"{primary}'s exposed skin and the clothing being removed stay clearly visible." ) if any(term in text for term in ("breast", "breasts", "nipple", "cupping breasts", "touching breasts")): return ( f"{primary} and {partner} press their bodies close while {partner}'s hand cups {primary}'s breast; " f"their faces stay close and the breast-touching gesture is clear." ) if any(term in text for term in ("face", "cheek", "jaw", "chin", "hand on the cheek", "fingers under the chin")): return ( f"{primary} and {partner} stand face-to-face at close range while one hand holds {primary}'s cheek and jaw; " f"their lips are close and the face-touching gesture is clear." ) if any(term in text for term in ("kiss", "kissing", "mouth-to-mouth", "lips pressed")): return ( f"{primary} and {partner} press their bodies together and kiss deeply, " f"with hands on each other's face, waist, and hips." ) return ( f"{primary} and {partner} are pressed close in a heated foreplay setup, " f"hands caressing skin while clothing is pulled aside." ) def interaction_text() -> str: return " ".join( str(part or "").lower() for part in ( item_text, *((item_axis_values or {}).values()), ) ) def manual_position_graph(primary: str, partner: str = "") -> str: text = interaction_text() if not partner: if "mutual" in text: return f"{primary} faces the camera with thighs open, both hands on her body for solo mutual-style masturbation framing." return f"{primary} reclines with thighs open, one hand between her legs and fingers visibly stimulating her pussy." if "mutual" in text: return f"{primary} and {partner} sit close facing each other, both touching themselves while keeping hands, faces, and bodies visible." if "clit" in text or "clitoris" in text: return f"{primary} reclines with thighs open while {partner}'s hand is between her legs, fingers rubbing her clit as her hips tilt toward the touch." if "toy" in text or "vibrator" in text: return f"{primary} reclines with thighs open while {partner} holds a vibrator or toy against her clit, one hand keeping her thigh open." return f"{primary} reclines with thighs open while {partner}'s hand is between her legs, fingers visibly stimulating her pussy." def interaction_position_graph(primary: str, partner: str, third: str = "") -> str: text = interaction_text() if "aftercare" in slug or any(term in text for term in ("aftercare", "cleanup", "wiping", "towel", "post-sex", "cuddle")): if "cleanup" in text or "wiping" in text or "towel" in text: return f"{primary} reclines after sex while {partner} kneels close and wipes her skin with a towel, hands and relaxed body contact visible." return f"{primary} and {partner} lie close together after sex, bodies relaxed and hands resting on skin in a post-sex cuddle." if "camera_performance" in slug or any(term in text for term in ("camera", "presenting", "showing", "viewer", "creator-shot")): if third: return f"{primary} faces the camera while {partner} and {third} hold and present her body, hands framing the exposed skin for the viewer." return f"{primary} faces the camera and presents her body while {partner}'s hands hold her hips or thighs open for a clear creator-shot reveal." if "body_worship" in slug or any(term in text for term in ("body worship", "nipple", "thigh", "mouth on skin", "kissing down", "ass grabbing")): if "ass" in text: return f"{primary} stands or kneels with hips angled back while {partner}'s hands grip her ass, fingers pressing into skin." if "thigh" in text: return f"{primary} reclines with thighs open while {partner} kneels close and kisses along her inner thighs, hands holding her legs in place." if "nipple" in text or "breast" in text: return f"{primary} arches toward {partner} while {partner}'s mouth is on her breast and one hand cups or squeezes the other breast." return f"{primary} reclines or leans back while {partner} kisses down her body, hands tracing breasts, waist, hips, and thighs." if "clothing_position" in slug or any(term in text for term in ("transition", "turning", "pulling onto", "lifting", "guided backward", "clothing", "garment")): if "turn" in text or "rear-facing" in text: return f"{partner}'s hands turn {primary} around by the hips, clothing partly moved aside as her body rotates into the next pose." if "legs" in text or "thigh" in text: return f"{primary} lies back while {partner} lifts and spreads her legs into position, hands and clothing movement clearly visible." return f"{primary} and {partner} are mid-transition, with {partner}'s hands moving clothing aside and guiding {primary}'s hips toward the next pose." if "dominant" in slug or any(term in text for term in ("hair", "wrist", "wrists", "jaw", "chin", "guided", "dominant", "control", "dirty talk", "whisper", "mouth near the ear", "verbal teasing")): if "dirty talk" in text or "whisper" in text or "mouth near the ear" in text or "verbal teasing" in text: return f"{partner} leans close to {primary}'s ear for dirty talk while holding her waist and keeping their bodies pressed close." if "wrist" in text or "wrists" in text: return f"{primary} lies back while {partner} pins her wrists above her head, both bodies close and the consensual control gesture clearly visible." if "hair" in text: return f"{partner} holds {primary}'s hair back while guiding her body closer, face and hair-hold gesture visible." if "thigh" in text or "spread" in text: return f"{primary} reclines with thighs open while {partner}'s hands spread her legs and hold the position for the camera." return f"{partner} guides {primary}'s body with hands on her jaw, waist, and hips, keeping the consensual control gesture readable." return foreplay_position_graph(primary, partner) def group_coordination_graph(primary: str, partner: str, third: str) -> str: observer = third or any_person({primary, partner}) text = interaction_text() if "camera" in text or "hold" in text or "present" in text: return f"{primary} is centered while {partner} and {observer} hold and present the body for the camera, each role clearly visible." if "watch" in text or "waiting" in text: return f"{primary} is centered while {partner} touches her body and {observer} watches close beside them, hands and faces readable." return f"{primary} is centered while {partner} touches her body and {observer} stays close as the watching or guiding partner." def mentions_ass(text: str) -> bool: return bool( re.search( r"\bass\b|ass[- ](?:up|raised|exposed|lifted)|spread cheeks|lower back and ass|cum (?:on|dripping from) ass|pussy, ass|ass and", text, ) ) def climax_position_graph(woman: str, man: str, third: str = "") -> str: if "lying between two partners" in item_text and third: return f"{woman} lies between {man} and {third}, with {man} under her hips and {third} positioned above her torso as visible semen lands on her body." if "held between front-and-back partners" in item_text and third: return f"{woman} is held between {man} behind her and {third} in front of her as visible semen lands across her body." if "kneeling between standing partners" in item_text and third: return f"{woman} kneels between {man} and {third} while both stand close around her face and torso for visible ejaculation." if "side-lying with thighs parted" in item_text: return f"{woman} lies on her side with thighs parted while {man} kneels beside her hips and ejaculates semen across her thighs and pussy." if "sitting on the edge of the bed" in item_text: return f"{woman} sits on the edge of the bed with knees spread while {man} stands close between her legs and ejaculates semen across her body." if "lying at the bed edge with thighs open" in item_text: return f"{woman} lies at the bed edge with thighs open while {man} kneels between her legs and ejaculates semen across her pussy and thighs." if "reclining with thighs open" in item_text or "lying on the back with legs spread" in item_text: return f"{woman} lies on her back with thighs open while {man} kneels between her legs and ejaculates semen across her pussy and thighs." if "on all fours with hips raised" in item_text: return f"{woman} is on all fours with hips raised while {man} is positioned behind her and ejaculates semen across her ass, thighs, and lower back." if "face-down ass-up" in item_text: return f"{woman} lies face-down with ass raised while {man} is positioned behind her and ejaculates semen across her lower back and ass." if "bent over with ass raised" in item_text or "bent over" in item_text: return f"{woman} is bent forward with hips raised while {man} is positioned behind her, visible semen across her lower back, ass, and thighs." if "kneeling with mouth open" in item_text: return f"{woman} kneels in front of {man} at hip height while {man} ejaculates semen onto her face, lips, and chest." if "kneeling in front of a standing partner" in item_text: return f"{woman} kneels in front of {man} at hip height while {man} stands over her for visible ejaculation." if "standing with cum on the body" in item_text: return f"{woman} stands braced in front of {man} while he stays close at hip level and ejaculates semen across her body." if "squatting on top of a partner" in item_text: return f"{woman} squats over {man}'s hips while {man} lies on his back under her and ejaculates semen onto her body." if "reverse cowgirl over a partner's hips" in item_text: return f"{woman} straddles {man}'s hips facing away while {man} lies on his back under her and ejaculates semen onto her body." if any(term in item_text for term in ("straddling a partner", "straddling a partner's hips", "shared climax after penetration", "orgasm during penetration")): return f"{woman} straddles {man}'s hips while {man} lies on his back under her, their bodies still aligned from penetration as he ejaculates semen onto her body." if "seated in a partner's lap facing them" in item_text: return f"{woman} sits in {man}'s lap facing him, legs wrapped around his hips as he ejaculates semen across her body." if any(term in item_text for term in ("lower back", "cum dripping from ass", "cum on lower back")) or mentions_ass(item_text): return f"{woman} is bent forward with hips raised while {man} is positioned behind her, visible semen across her lower back, ass, and thighs." if any(term in item_text for term in ("cum on face", "cum on tongue", "cum on lips", "cum on face and lips", "cum on tongue and chin")): if third: return f"{woman} kneels in the center while {man} and {third} stand close around her face and torso for visible ejaculation." return f"{woman} kneels in front of {man} at hip height while {man} ejaculates semen onto her face, lips, and chest." return f"{woman} lies on her back with thighs open while {man} kneels between her legs and ejaculates semen onto her body." def penetration_position_graph(woman: str, man: str) -> str: text = " ".join( str(part or "").lower() for part in ( item_text, *((item_axis_values or {}).values()), ) ) if "missionary" in text: return ( f"{woman} lies on her back with legs open around {man}'s hips while {man} is above her between her thighs; " f"{man}'s hips press close and {man}'s penis thrusts into her pussy." ) if "reverse cowgirl" in text: return f"{woman} straddles {man}'s hips facing away while {man} lies under her and {man}'s penis thrusts into her pussy." if "cowgirl" in text or "straddling" in text: return f"{woman} straddles {man}'s hips facing him while {man} lies under her and {man}'s penis thrusts into her pussy." if "doggy" in text or "rear-entry" in text or "bent-over" in text or "bent over" in text: return f"{woman} is on all fours with hips raised while {man} is positioned behind her and {man}'s penis thrusts into her pussy." if "standing" in text: return f"{woman} stands braced with hips angled back while {man} stands behind her and {man}'s penis thrusts into her pussy." if "spooning" in text or "side-lying" in text: return f"{woman} lies on her side with thighs parted while {man} presses behind her and {man}'s penis thrusts into her pussy." if "edge-of-bed" in text or "edge of bed" in text or "bed edge" in text or "edge-supported" in text or "raised edge" in text: return ( f"{woman} lies back at a raised edge with hips at the edge and legs open while {man} kneels between her thighs; " f"{man}'s hips press close and {man}'s penis thrusts into her pussy." ) if "kneeling straddle" in text: return f"{woman} kneels straddling {man}'s hips while {man} supports her waist and {man}'s penis thrusts into her pussy." if "lotus" in text: return f"{woman} sits in {man}'s lap facing him with legs around his hips while {man}'s penis thrusts into her pussy." return ( f"{woman} lies on her back with legs spread wide and knees bent outward while {man} kneels between her open thighs facing her; " f"{man}'s hips are pressed between her legs and {man}'s penis thrusts into her pussy." ) def anal_position_graph(woman: str, man: str) -> str: text = " ".join( str(part or "").lower() for part in ( item_text, *((item_axis_values or {}).values()), ) ) if "bent-over" in text or "bent over" in text: return f"{woman} is bent forward with hips raised while {man} stands behind her and thrusts his penis into her ass." if "face-down" in text: return f"{woman} lies face-down with ass raised while {man} is positioned behind her and thrusts his penis into her ass." if "doggy" in text or "rear-entry" in text: return f"{woman} is on all fours with hips raised while {man} is positioned behind her and thrusts his penis into her ass." if "standing" in text: return f"{woman} stands braced with hips angled back while {man} stands behind her and thrusts his penis into her ass." if "spooning" in text or "side-lying" in text: return f"{woman} lies on her side with thighs parted while {man} presses behind her and thrusts his penis into her ass." if "edge-of-bed" in text or "edge of bed" in text or "bed edge" in text: return f"{woman} lies near a raised edge with hips exposed while {man} kneels behind her and thrusts his penis into her ass." if "kneeling" in text: return f"{woman} kneels forward with hips raised while {man} kneels behind her and thrusts his penis into her ass." return f"{woman} is on all fours with hips raised while {man} is positioned behind her and thrusts his penis into her ass." def outercourse_position_graph(woman: str, man: str) -> str: position_text = str((item_axis_values or {}).get("position") or "").lower() text = " ".join( str(part or "").lower() for part in ( item_text, *((item_axis_values or {}).values()), ) ) man_is_pov = man in pov_set if any(term in text for term in ("boobjob", "titjob", "breast-sex", "breast sex")): if man_is_pov: return ( f"{woman} kneels between the POV viewer's open thighs with her torso bent forward over his pelvis and shoulders low, " "both hands lifting and pressing her breasts tightly around the POV viewer's penis shaft while the glans sits just below her lips." ) return ( f"{woman} kneels between {man}'s open thighs with her torso bent forward over his pelvis and shoulders low while {man} sits with legs apart, " f"{woman}'s hands lifting and pressing her breasts tightly around {man}'s penis shaft while the glans sits just below her lips." ) if any(term in text for term in ("testicle", "balls-licking", "balls licking", "balls and mouth", "balls held")): if man_is_pov: return ( f"{woman} kneels very low between the POV viewer's open thighs with her torso bent forward and shoulders between his knees, " "head tucked under the penis shaft at the base of the penis, mouth and tongue on the POV viewer's balls while his penis points upward above her face." ) return ( f"{man} sits with legs apart while {woman} kneels very low between his open thighs with her torso bent forward and shoulders between his knees, " f"head tucked under the penis shaft at the base of his penis, mouth and tongue on his balls while {man}'s penis points upward above her face." ) if "penis-licking" in position_text or "penis licking" in text or "tongue along" in text or "tongue licking" in text: if man_is_pov: return ( f"{woman} bends forward between the POV viewer's open thighs, head low under the POV viewer's penis with her face directly under the penis, " "tongue running along the underside from the penis shaft to the glans while one hand steadies the base of the penis." ) return ( f"{woman} bends forward between {man}'s open thighs, head low under {man}'s penis with her face directly under the penis, " f"tongue running along the underside from the penis shaft to the glans while one hand steadies the base of the penis." ) if "handjob" in position_text or "handjob" in text or "hand job" in text or "hand wrapped" in text: if man_is_pov: return ( f"{woman} kneels between the POV viewer's open thighs with her torso leaning forward and face visible behind the penis shaft, " "one hand wrapped around the POV viewer's penis shaft while the other hand steadies the base of the penis as she strokes toward the glans." ) return ( f"{woman} kneels between {man}'s open thighs with her torso leaning forward and face visible behind the penis shaft, " f"one hand wrapped around {man}'s penis shaft while the other hand steadies the base of the penis as she strokes toward the glans." ) if "footjob" in text or "soles" in text or "toes curled" in text or "feet stroking" in text: if man_is_pov: return ( f"{woman} faces the POV viewer with her hips back, torso visible behind her raised legs, and both knees bent open toward the camera, " "both soles wrapped around the POV viewer's penis shaft in the lower foreground." ) return ( f"{man} reclines with hips forward while {woman} faces him with her hips back and both knees bent open, " f"wrapping both soles around {man}'s penis shaft while the contact stays centered." ) if man_is_pov: return ( f"{woman} kneels close to the POV viewer's hips and keeps the POV viewer's penis centered in clear non-penetrative contact, " "with her mouth, hands, breasts, or feet visibly working around the penis shaft." ) return ( f"{woman} kneels close to {man}'s hips and keeps {man}'s penis centered in clear non-penetrative contact, " "with her mouth, hands, breasts, or feet visibly working around the penis shaft." ) def oral_position_graph(woman: str, man: str) -> str: position_text = str((item_axis_values or {}).get("position") or "").lower() text = " ".join( str(part or "").lower() for part in ( item_text, *((item_axis_values or {}).values()), ) ) man_is_pov = man in pov_set woman_gives = any( term in text for term in ( "fellatio", "blowjob", "deepthroat", "penis sucking", "penis in mouth", "penis in her mouth", "mouth stretched around a penis", "lips wrapped", ) ) man_gives = any( term in text for term in ( "cunnilingus", "pussy licking", "tongue on pussy", "mouth on pussy", "pussy and tongue", "face-sitting", "tongue contact clearly visible", ) ) if "mouth on genitals" in text and not woman_gives and not man_gives: if any(term in text for term in ("face-sitting", "reclining", "straddled", "spread-leg", "open thighs")): man_gives = True else: woman_gives = True if "sixty-nine" in position_text or ("sixty-nine" in text and not position_text): return f"{woman} and {man} lie head-to-hips in a sixty-nine position, with {woman}'s mouth on {man}'s penis and {man}'s mouth on {woman}'s pussy." if "face-sitting" in position_text or ("face-sitting" in text and not position_text): if man_is_pov: return ( f"{woman} is above the POV camera, straddling the POV viewer's face with thighs on both sides of his head, " "pussy directly over the POV viewer's mouth for close first-person underview tongue contact." ) return f"{man} lies on his back while {woman} straddles his face with her thighs around his head and {man}'s mouth pressed to her pussy." if "straddled oral" in position_text or ("straddled oral" in text and not position_text): if woman_gives and not man_gives: return f"{man} straddles forward near {woman}'s face while {woman} kneels below him with her mouth on his penis." return f"{woman} straddles above {man}'s face with her thighs framing his head while {man}'s mouth stays pressed to her pussy." if "side-lying oral" in position_text or ("side-lying oral" in text and not position_text): if woman_gives and not man_gives: return f"{man} lies on his side with hips angled toward {woman} while {woman} lies beside his thighs and takes his penis in her mouth." return f"{woman} lies on her side with her top thigh lifted while {man} lies beside her hips with his mouth pressed to her pussy." if ( "edge-of-bed oral" in position_text or "edge of bed oral" in position_text or "edge-supported oral" in position_text or (("edge-of-bed oral" in text or "edge of bed oral" in text or "edge-supported oral" in text) and not position_text) ): if woman_gives and not man_gives: return f"{man} sits at a raised edge with legs apart while {woman} kneels between his thighs and takes his penis in her mouth." return f"{woman} lies at a raised edge with thighs open while {man} kneels between her legs with his mouth on her pussy." if "standing oral" in position_text or ("standing oral" in text and not position_text): if man_gives and not woman_gives: return f"{woman} stands braced with one thigh lifted while {man} kneels between her legs with his mouth on her pussy." return f"{man} stands with hips forward while {woman} kneels in front of him at hip height and takes his penis in her mouth." if "chair oral" in position_text or ("chair oral" in text and not position_text): if man_gives and not woman_gives: return f"{woman} sits in a chair with thighs open while {man} kneels between her legs with his mouth pressed to her pussy." return f"{man} sits in a chair with legs apart while {woman} kneels between his thighs and takes his penis in her mouth." if ( "reclining cunnilingus" in position_text or "spread-leg oral" in position_text or (("reclining cunnilingus" in text or "spread-leg oral" in text) and not position_text) ): if woman_gives and not man_gives: return f"{man} reclines with legs apart while {woman} kneels between his thighs and takes his penis in her mouth." return f"{woman} reclines on her back with thighs spread while {man} kneels between her legs with his mouth on her pussy." if "kneeling oral" in position_text or ("kneeling oral" in text and not position_text): if man_gives and not woman_gives: return f"{woman} kneels with thighs parted and hips angled forward while {man} kneels in front of her with his mouth on her pussy." return ( f"{woman} kneels in front of {man}'s penis while {man} stands over her; " f"{woman} takes {man}'s penis in her mouth with saliva dripping on the penis as {man} looks down toward her." ) if man_gives and not woman_gives: return f"{woman} lies on her back with thighs open while {man} kneels between her legs with his mouth pressed to her pussy." return f"{woman} kneels in front of {man}'s hips and takes his penis in her mouth while {man} keeps his hips aligned with her face." if people_count == 1: solo = people[0] if women_count == 1: if "manual_stimulation" in slug: return manual_position_graph(solo) if "camera_performance" in slug: return f"{solo} faces the camera and presents her body with hands framing the exposed skin in a solo creator-shot pose." if "cumshot" in slug or "climax" in slug: return f"{solo} is shown in a solo explicit orgasm pose with thighs open, one hand on her body, and visible arousal on skin and sheets." return f"{solo} is shown in a solo explicit adult pose with self-touch, open body framing, and direct camera awareness." if "cumshot" in slug or "climax" in slug: return f"{solo} is shown in a solo visible ejaculation pose with one hand on his penis, body angled toward the camera, and semen visible." return f"{solo} is shown in a solo explicit adult pose with direct camera awareness and clear body framing." if women_count > 0 and men_count == 0: a, b = _pick_distinct(rng, women, 2) c = any_woman({a, b}) if len(women) >= 3 else "" used = {a, b} if "manual_stimulation" in slug: graph = manual_position_graph(a, b) elif "group_coordination" in slug and c: graph = group_coordination_graph(a, b, c) used.add(c) elif any(token in slug for token in ("foreplay", "body_worship", "clothing_position", "dominant_guidance", "camera_performance", "aftercare")): graph = interaction_position_graph(a, b, c) if c and "camera_performance" in slug: used.add(c) elif "foreplay" in slug: graph = foreplay_position_graph(a, b) elif "outercourse" in slug: graph = f"{a} kneels close to {b}'s body and uses mouth, hands, breasts, or feet for explicit non-penetrative contact." elif "oral" in slug: graph = f"{a} kneels between {b}'s spread thighs and uses tongue and fingers on her pussy." elif "anal" in slug or "double" in slug: graph = f"{a} uses a strap-on on {b} while keeping her hips held open." elif "threesome" in slug or "group" in slug or "orgy" in slug: helper = c or any_woman({a}) graph = f"{a} uses a strap-on on {b} while {helper} gives oral contact and touches both bodies." used.add(helper) elif "cumshot" in slug or "climax" in slug: graph = f"{a} brings {b} to orgasm with mouth and fingers while wetness is visible on thighs and sheets." else: graph = f"{a} uses a strap-on on {b} while their bodies stay pressed together." return graph + support_sentence(used) if men_count > 0 and women_count == 0: a, b = _pick_distinct(rng, men, 2) c = any_man({a, b}) if len(men) >= 3 else "" used = {a, b} if "manual_stimulation" in slug: graph = f"{a} and {b} sit or recline close together with hands visibly stimulating bodies in a manual sex setup." elif "group_coordination" in slug and c: graph = group_coordination_graph(a, b, c) used.add(c) elif any(token in slug for token in ("foreplay", "body_worship", "clothing_position", "dominant_guidance", "camera_performance", "aftercare")): graph = f"{a} and {b} press close together, kissing and caressing skin while clothing is pulled aside." elif "foreplay" in slug: graph = f"{a} and {b} press close together, kissing and caressing skin while clothing is pulled aside." elif "outercourse" in slug: graph = f"{a} and {b} keep explicit non-penetrative penis contact visible with hands, mouth, or feet." elif "oral" in slug: graph = f"{a} kneels and takes {b}'s penis in his mouth while holding his hips." elif "anal" in slug or "double" in slug or "penetrative" in slug: graph = f"{a} penetrates {b} anally while {b}'s hips are held open." elif "threesome" in slug or "group" in slug or "orgy" in slug: helper = c or any_man({a}) graph = f"{a} penetrates {b} anally while {helper} gives oral contact from the front." used.add(helper) elif "cumshot" in slug or "climax" in slug: graph = f"{a} ejaculates semen over {b}'s body while {b} keeps eye contact and one hand on his penis." else: graph = f"{a} and {b} keep explicit penis and anal contact visible." return graph + support_sentence(used) woman = any_woman() man = any_man() third = any_person({woman, man}) if people_count >= 3 else "" if "manual_stimulation" in slug: graph = manual_position_graph(woman, man) elif "group_coordination" in slug: graph = group_coordination_graph(woman, man, third) elif any(token in slug for token in ("foreplay", "body_worship", "clothing_position", "dominant_guidance", "camera_performance", "aftercare")): graph = interaction_position_graph(woman, man, third) elif "foreplay" in slug: graph = foreplay_position_graph(woman, man) elif "outercourse" in slug: graph = outercourse_position_graph(woman, man) elif "oral" in slug: graph = oral_position_graph(woman, man) elif "anal" in slug or "double" in slug: if "double" in item_text or "toy" in item_text: if people_count >= 3: graph = f"{man} thrusts his penis into {woman} while {third} adds a second penetration point from the front." else: if "bent-over" in item_text or "bent over" in item_text: graph = f"{woman} is bent forward with hips raised while {man} is positioned behind her and thrusts his penis into her ass." elif "face-down" in item_text: graph = f"{woman} lies face-down with hips raised while {man} is positioned behind her and thrusts his penis into her ass." elif "standing" in item_text: graph = f"{woman} stands braced with hips raised while {man} is positioned behind her and thrusts his penis into her ass." elif "kneeling" in item_text: graph = f"{woman} kneels forward with hips raised while {man} is positioned behind her and thrusts his penis into her ass." else: graph = f"{woman} is on all fours with hips raised while {man} is positioned behind her and thrusts his penis into her ass." elif people_count >= 3: graph = f"{man} thrusts his penis into {woman} while {third} gives oral contact from the front." else: graph = anal_position_graph(woman, man) elif "threesome" in slug: graph = f"{man} thrusts his penis into {woman} while {third or any_person({woman, man})} uses mouth and hands on the exposed body." elif "group" in slug or "orgy" in slug: graph = f"{man} thrusts his penis into {woman} while surrounding partners give oral contact and keep hands on hips, breasts, and thighs." elif "cumshot" in slug or "climax" in slug: graph = climax_position_graph(woman, man, third) else: graph = penetration_position_graph(woman, man) return graph + support_sentence({woman, man, third} if third else {woman, man})