condition_axis._base

Shared utilities for condition axis generation system.

This module provides common functionality used by all condition axis generators (character, facial, occupation, etc.) to maintain consistency and reduce code duplication.

The condition axis system is a structured, rule-based framework for generating coherent state descriptions across multiple dimensions. It is used for: - Procedural character generation (MUD/IF games) - Image generation prompt construction - Narrative content generation

Core concepts: - Axes: Semantic dimensions with discrete values (e.g., physique: skinny, wiry, stocky) - Weights: Probability distributions for realistic populations - Exclusions: Semantic constraints to prevent illogical combinations - Policy: Rules for mandatory vs. optional axes

condition_axis._base.apply_exclusion_rules(chosen, exclusions)[source]

Apply semantic exclusion rules to remove illogical combinations.

Exclusion rules encode domain knowledge about incompatible combinations. For example: “wealthy + frail” is unlikely (wealth enables health care), or “ancient + timid” is incoherent (age brings confidence).

Parameters:
  • chosen (dict[str, str]) – Dictionary mapping axis names to selected values. Modified in-place as exclusions are applied.

  • exclusions (dict[tuple[str, str], dict[str, list[str]]]) – Dictionary of exclusion rules. Format: {(axis, value): {blocked_axis: [blocked_values]}} Example: {(“wealth”, “decadent”): {“health”: [“sickly”]}}

Return type:

dict[str, str]

Returns:

The modified chosen dictionary (same reference, for convenience)

Examples

>>> chosen = {"wealth": "decadent", "health": "sickly"}
>>> exclusions = {("wealth", "decadent"): {"health": ["sickly"]}}
>>> apply_exclusion_rules(chosen, exclusions)
{'wealth': 'decadent'}  # health removed due to conflict
>>> chosen = {"age": "young", "demeanor": "alert"}
>>> exclusions = {("age", "ancient"): {"demeanor": ["timid"]}}
>>> apply_exclusion_rules(chosen, exclusions)
{'age': 'young', 'demeanor': 'alert'}  # no exclusion triggered

Notes

  • Modifies the chosen dict in-place

  • Logs all applied exclusions at DEBUG level

  • Returns the same dict reference for chaining

  • Removal order is deterministic (dict iteration order)

condition_axis._base.values_to_prompt(condition_dict)[source]

Convert structured condition data to a comma-separated prompt fragment.

This is the canonical serialization format for condition axis data. The output is designed to be: - Human-readable - Diffusion model friendly (comma-separated keywords) - Consistent across all condition axis types

Parameters:

condition_dict (dict[str, str]) – Dictionary mapping axis names to values (output from any generate_* function)

Return type:

str

Returns:

Comma-separated string of condition values. Order is deterministic (Python 3.7+ dict insertion order). Empty dict returns empty string.

Examples

>>> values_to_prompt({"physique": "wiry", "wealth": "poor"})
'wiry, poor'
>>> values_to_prompt({"physique": "stocky", "wealth": "modest", "age": "old"})
'stocky, modest, old'
>>> values_to_prompt({})
''

Notes

  • Only includes values, not axis names (for prompt clarity)

  • Maintains insertion order from generation

  • Can be extended for different output formats (JSON, prose, etc.)

condition_axis._base.weighted_choice(options, weights=None, rng=None)[source]

Select a random option with optional weighted probabilities.

This is the core selection mechanism for all condition axis generators. It enables both uniform and weighted probability distributions, allowing for realistic population modeling (e.g., “poor” is more common than “wealthy”).

Parameters:
  • options (list[str]) – List of possible values to choose from. Must be non-empty.

  • weights (dict[str, float] | None) – Optional dictionary mapping options to weights. If None or missing entries, defaults to uniform distribution. Weights must be non-negative (zero weight = never selected).

  • rng (Random | None) – Optional Random instance for isolated random generation. If None, uses global random module.

Return type:

str

Returns:

Randomly selected option (str)

Examples

>>> # Uniform distribution (all equally likely)
>>> weighted_choice(["a", "b", "c"])
'b'
>>> # Weighted distribution (biased toward common values)
>>> weighted_choice(["rare", "common"], {"rare": 1.0, "common": 5.0})
'common'
>>> # Partial weights (missing options default to 1.0)
>>> weighted_choice(["a", "b", "c"], {"a": 3.0})  # a=3.0, b=1.0, c=1.0
'a'
>>> # With isolated RNG
>>> rng = random.Random(42)
>>> weighted_choice(["a", "b", "c"], rng=rng)
'a'

Notes

  • Uses random.choices() for weighted selection

  • Falls back to random.choice() for uniform distribution (performance)

  • When rng is provided, uses isolated Random instance (thread-safe)

  • When rng is None, uses global random module (backward compatible)