Filter anal axis details for position compatibility
This commit is contained in:
+93
-1
@@ -292,6 +292,96 @@ def outercourse_axis_values_for_position(values: list[Any], position: str, axis_
|
||||
return values
|
||||
|
||||
|
||||
def anal_axis_values_for_position(values: list[Any], position: str, axis_name: str) -> list[Any]:
|
||||
position_text = str(position or "").lower()
|
||||
if not position_text:
|
||||
return values
|
||||
axis_name = str(axis_name or "").lower()
|
||||
if axis_name not in {"body_contact", "hand_detail", "leg_detail", "thrust_detail", "visibility"}:
|
||||
return values
|
||||
|
||||
def value_text(value: Any) -> str:
|
||||
return entry_text(value).lower()
|
||||
|
||||
def filtered(terms: tuple[str, ...], excluded_terms: tuple[str, ...] = ()) -> list[Any]:
|
||||
matches = [
|
||||
value
|
||||
for value in values
|
||||
if any(term in value_text(value) for term in terms)
|
||||
and not any(term in value_text(value) for term in excluded_terms)
|
||||
]
|
||||
if matches:
|
||||
return matches
|
||||
if excluded_terms:
|
||||
non_excluded = [
|
||||
value
|
||||
for value in values
|
||||
if not any(term in value_text(value) for term in excluded_terms)
|
||||
]
|
||||
if non_excluded:
|
||||
return non_excluded
|
||||
return values
|
||||
|
||||
if "side-lying" in position_text or "spooning" in position_text:
|
||||
by_axis = {
|
||||
"body_contact": ("bodies locked", "chests pressed", "sweaty", "hips pressed"),
|
||||
"hand_detail": ("hips", "waist", "cheeks", "shoulders"),
|
||||
"leg_detail": ("one leg lifted", "thighs held open", "legs spread"),
|
||||
"thrust_detail": ("pelvis pressed", "bodies rocking", "wet skin", "hard grinding"),
|
||||
"visibility": ("ass and penis", "anal penetration", "spread cheeks", "genital contact"),
|
||||
}
|
||||
return filtered(
|
||||
by_axis.get(axis_name, ("side", "thigh", "hips")),
|
||||
("standing", "kneeling", "draped over shoulders", "knees pressed to chest"),
|
||||
)
|
||||
if "standing" in position_text:
|
||||
by_axis = {
|
||||
"body_contact": ("hips pressed", "bodies locked", "one body bent over", "ass lifted", "sweaty"),
|
||||
"hand_detail": ("hips", "waist", "cheeks", "shoulders"),
|
||||
"leg_detail": ("standing", "one foot planted"),
|
||||
"thrust_detail": ("hips", "pelvis", "hard grinding", "bodies rocking"),
|
||||
"visibility": ("ass and penis", "anal penetration", "spread cheeks", "genital contact"),
|
||||
}
|
||||
return filtered(
|
||||
by_axis.get(axis_name, ("standing", "hips")),
|
||||
("kneeling", "draped over shoulders", "knees pressed to chest", "side-lying"),
|
||||
)
|
||||
if "edge-of-bed" in position_text or "bed-edge" in position_text or "edge supported" in position_text:
|
||||
by_axis = {
|
||||
"body_contact": ("thighs held open", "hips pressed", "bodies locked", "ass lifted"),
|
||||
"hand_detail": ("hips", "waist", "cheeks", "thighs"),
|
||||
"leg_detail": ("knees pressed", "legs draped", "thighs held open", "one foot planted"),
|
||||
"thrust_detail": ("hips", "pelvis", "hard grinding", "bodies rocking"),
|
||||
"visibility": ("ass and penis", "anal penetration", "open thighs", "genital contact"),
|
||||
}
|
||||
return filtered(by_axis.get(axis_name, ("thigh", "hips")), ("standing", "side-lying"))
|
||||
if "kneeling" in position_text:
|
||||
by_axis = {
|
||||
"body_contact": ("ass lifted", "hips pressed", "bodies locked", "one body bent over"),
|
||||
"hand_detail": ("hips", "waist", "cheeks", "thighs"),
|
||||
"leg_detail": ("kneeling", "thighs held open", "legs spread"),
|
||||
"thrust_detail": ("hips", "pelvis", "ass pushed", "hard grinding"),
|
||||
"visibility": ("ass and penis", "anal penetration", "spread cheeks", "genital contact"),
|
||||
}
|
||||
return filtered(
|
||||
by_axis.get(axis_name, ("kneeling", "hips")),
|
||||
("standing", "draped over shoulders", "knees pressed to chest", "side-lying"),
|
||||
)
|
||||
if "doggy" in position_text or "face-down" in position_text or "bent-over" in position_text:
|
||||
by_axis = {
|
||||
"body_contact": ("ass lifted", "one body bent over", "hips pressed", "bodies locked"),
|
||||
"hand_detail": ("hips", "waist", "cheeks", "thighs"),
|
||||
"leg_detail": ("legs spread", "kneeling", "one foot planted", "standing"),
|
||||
"thrust_detail": ("ass pushed", "hips", "pelvis", "hard grinding"),
|
||||
"visibility": ("ass and penis", "anal penetration", "spread cheeks", "genital contact"),
|
||||
}
|
||||
excluded = ("side-lying", "draped over shoulders", "knees pressed to chest")
|
||||
if "face-down" in position_text or "doggy" in position_text:
|
||||
excluded = (*excluded, "standing")
|
||||
return filtered(by_axis.get(axis_name, ("ass", "hips")), excluded)
|
||||
return values
|
||||
|
||||
|
||||
def _format(template: str, context: dict[str, Any]) -> str:
|
||||
fields = {key for _, key, _, _ in Formatter().parse(template) if key}
|
||||
safe_context = SafeFormatDict({key: "" for key in fields})
|
||||
@@ -317,7 +407,7 @@ def compose_item(
|
||||
unique_fields = list(dict.fromkeys(fields))
|
||||
axis_values: dict[str, str] = {}
|
||||
subcategory_slug = str(subcategory.get("slug") or "").lower()
|
||||
if subcategory_slug in ("oral_sex", "outercourse_sex") and "position" in unique_fields and axes.get("position"):
|
||||
if subcategory_slug in ("oral_sex", "outercourse_sex", "anal_double_penetration") and "position" in unique_fields and axes.get("position"):
|
||||
position_values = category_policy.compatible_entries(axes["position"], women_count, men_count)
|
||||
axis_values["position"] = entry_text(weighted_choice(rng, position_values))
|
||||
for name in unique_fields:
|
||||
@@ -337,6 +427,8 @@ def compose_item(
|
||||
values = outercourse_acts_for_position(values, axis_values.get("position", ""))
|
||||
if subcategory_slug == "outercourse_sex":
|
||||
values = outercourse_axis_values_for_position(values, axis_values.get("position", ""), name)
|
||||
if subcategory_slug == "anal_double_penetration":
|
||||
values = anal_axis_values_for_position(values, axis_values.get("position", ""), name)
|
||||
axis_values[name] = entry_text(weighted_choice(rng, values))
|
||||
item_prompt = _format(template, axis_values).strip()
|
||||
name = item_name(item) or subcategory["name"]
|
||||
|
||||
Reference in New Issue
Block a user