GameConfigIdea / song_scenarios.py
kwabs22
Port changes from duplicate space to original
9328e91
"""Song/Lyrics emotional journey data and sequence generation.
This module provides:
- EMOTIONAL_STATES: Dictionary of emotional states for song-based narratives
- generate_song_sequence: Function to generate emotional journey sequences
"""
import json
import random
# Emotional states organized by mood category
EMOTIONAL_STATES = {
"joy": [
("Euphoria", "Pure, overwhelming happiness radiates through every moment", ["celebration", "peak"]),
("Contentment", "A gentle satisfaction with the present moment", ["peace", "gratitude"]),
("Excitement", "Anticipation of wonderful things bubbles up inside", ["energy", "possibility"]),
("Love's Bloom", "The warmth of affection fills every corner of being", ["romance", "connection"]),
("Triumph", "Victory brings a surge of proud accomplishment", ["achievement", "power"]),
],
"sorrow": [
("Heartbreak", "The ache of loss echoes through an empty chest", ["pain", "separation"]),
("Melancholy", "A bittersweet sadness colors everything in blue", ["reflection", "beauty"]),
("Grief", "The weight of absence presses down relentlessly", ["mourning", "memory"]),
("Longing", "An unreachable desire stretches toward the horizon", ["yearning", "distance"]),
("Regret", "If only things had been different...", ["hindsight", "weight"]),
],
"anger": [
("Rage", "White-hot fury demands expression and release", ["intensity", "destruction"]),
("Frustration", "Barriers block every attempt at progress", ["struggle", "tension"]),
("Betrayal", "Trust shattered leaves sharp edges everywhere", ["wound", "disbelief"]),
("Defiance", "A refusal to accept what others demand", ["rebellion", "strength"]),
("Righteous Fire", "Injustice ignites a burning need for action", ["purpose", "conviction"]),
],
"fear": [
("Dread", "Something terrible approaches with inevitable footsteps", ["anticipation", "darkness"]),
("Anxiety", "Uncertainty spirals into cascading worries", ["overwhelm", "paralysis"]),
("Vulnerability", "Exposed and unprotected in a hostile world", ["fragility", "need"]),
("Paranoia", "Every shadow hides a threat, every silence a danger", ["suspicion", "isolation"]),
("Terror", "Primal fear strips away everything but survival", ["crisis", "instinct"]),
],
"hope": [
("Dawn Breaking", "After darkness, the first light of possibility appears", ["renewal", "promise"]),
("Second Chance", "An opportunity to make things right emerges", ["redemption", "gratitude"]),
("Dreams Forming", "Visions of what could be take shape in the mind", ["imagination", "aspiration"]),
("Faith Restored", "Belief in something greater returns", ["trust", "meaning"]),
("Courage Rising", "Fear transforms into determination to face what comes", ["strength", "resolve"]),
],
"nostalgia": [
("Golden Memories", "The past glows with a warm, amber light", ["comfort", "loss"]),
("Innocence Lost", "Remembering before the world became complicated", ["youth", "purity"]),
("Phantom Touch", "The sensation of someone no longer present", ["love", "absence"]),
("Places Remembered", "Spaces that hold pieces of who you were", ["identity", "change"]),
("Old Songs", "Melodies that transport you across time", ["emotion", "connection"]),
],
"peace": [
("Stillness", "The noise fades and silence becomes sanctuary", ["calm", "presence"]),
("Acceptance", "What is, simply is - no struggle remains", ["surrender", "wisdom"]),
("Unity", "Separation dissolves into connection with all things", ["transcendence", "belonging"]),
("Forgiveness", "The weight of grudges lifts away", ["release", "healing"]),
("Home", "A sense of belonging settles into the bones", ["safety", "arrival"]),
],
}
# Song structure elements
SONG_STRUCTURES = {
"verse": "The story unfolds, details emerge",
"chorus": "The central truth repeats, driving home the message",
"bridge": "A shift in perspective, a new angle on the theme",
"outro": "The emotion settles, leaving its lasting impression",
}
def generate_song_sequence(verse_count, include_joy, include_sorrow, include_anger,
include_fear, include_hope, include_nostalgia, include_peace,
emotional_arc="journey"):
"""Generate an emotional journey sequence based on song structure.
Args:
verse_count: Number of emotional beats (3-10)
include_*: Include specific emotional categories
emotional_arc: 'journey' (varied), 'crescendo' (building), 'resolution' (tension to peace)
Returns:
Tuple of (list_output, json_output, prompts_output)
"""
available = []
if include_joy:
available.extend([(e[0], e[1], "joy", e[2]) for e in EMOTIONAL_STATES["joy"]])
if include_sorrow:
available.extend([(e[0], e[1], "sorrow", e[2]) for e in EMOTIONAL_STATES["sorrow"]])
if include_anger:
available.extend([(e[0], e[1], "anger", e[2]) for e in EMOTIONAL_STATES["anger"]])
if include_fear:
available.extend([(e[0], e[1], "fear", e[2]) for e in EMOTIONAL_STATES["fear"]])
if include_hope:
available.extend([(e[0], e[1], "hope", e[2]) for e in EMOTIONAL_STATES["hope"]])
if include_nostalgia:
available.extend([(e[0], e[1], "nostalgia", e[2]) for e in EMOTIONAL_STATES["nostalgia"]])
if include_peace:
available.extend([(e[0], e[1], "peace", e[2]) for e in EMOTIONAL_STATES["peace"]])
if not available:
return "Select at least one emotional category!", "{}", ""
sequence = []
random.shuffle(available)
# Apply emotional arc logic
if emotional_arc == "crescendo":
# Build from calm to intense
intensity_order = ["peace", "nostalgia", "hope", "joy", "fear", "sorrow", "anger"]
available.sort(key=lambda x: intensity_order.index(x[2]) if x[2] in intensity_order else 3)
elif emotional_arc == "resolution":
# Start intense, end peaceful
intense = [e for e in available if e[2] in ["anger", "fear", "sorrow"]]
calm = [e for e in available if e[2] in ["peace", "hope", "joy"]]
random.shuffle(intense)
random.shuffle(calm)
available = intense + calm
sequence = available[:verse_count]
if not sequence:
return "No emotional states available!", "{}", ""
# Assign song structure elements
structure_labels = []
for i in range(len(sequence)):
if i == 0:
structure_labels.append("INTRO")
elif i == len(sequence) - 1:
structure_labels.append("OUTRO")
elif i == len(sequence) // 2:
structure_labels.append("BRIDGE")
elif i % 2 == 0:
structure_labels.append("CHORUS")
else:
structure_labels.append("VERSE")
# Format as list
list_output = f"## Emotional Journey ({emotional_arc.title()} Arc)\n\n"
for i, ((name, desc, mood, themes), structure) in enumerate(zip(sequence, structure_labels), 1):
themes_str = ", ".join(themes)
list_output += f"**{i}. [{structure}] {name}** ({mood})\n{desc}\n*Themes: {themes_str}*\n\n"
# Format as config JSON
config = {"emotional_journey": {}}
for i, ((name, desc, mood, themes), structure) in enumerate(zip(sequence, structure_labels), 1):
state_name = name.lower().replace(" ", "_").replace("'", "").replace("-", "_")
current_state_id = f"moment_{i}_{state_name}"
themes_str = ", ".join(themes)
# Determine next state
if i < len(sequence):
next_name = sequence[i][0]
next_state_name = next_name.lower().replace(" ", "_").replace("'", "").replace("-", "_")
next_state_id = f"moment_{i+1}_{next_state_name}"
else:
next_state_id = "journey_end"
config["emotional_journey"][current_state_id] = {
"description": f"[{structure}] {desc}\n\n*Feeling: {mood} | {themes_str}*",
"media_prompt": f"Abstract emotional art: {name} - {mood} mood, {desc}, visual representation of {themes_str}",
"choices": ["Feel the Next Wave"],
"transitions": {
"Feel the Next Wave": next_state_id
}
}
# Add ending state
first_moment = sequence[0][0].lower().replace(" ", "_").replace("'", "").replace("-", "_")
config["emotional_journey"]["journey_end"] = {
"description": "The emotional journey comes full circle. Every feeling has been felt, every moment lived.",
"choices": ["Experience Again"],
"transitions": {
"Experience Again": f"moment_1_{first_moment}"
}
}
json_output = json.dumps(config, indent=2)
# Format prompts
prompts_output = f"## Emotional Art Prompts ({emotional_arc.title()})\n\n"
for i, (name, desc, mood, themes) in enumerate(sequence, 1):
themes_str = ", ".join(themes)
prompts_output += f"Abstract emotional art: {name} - {mood}, {themes_str}\n"
return list_output, json_output, prompts_output
if __name__ == "__main__":
list_out, json_out, prompts_out = generate_song_sequence(
6, True, True, False, False, True, True, True, "resolution"
)
print(list_out)