"""Film scenario data and sequence generation. This module provides: - FILM_SCENARIOS: Dictionary of categorized film scenario templates - generate_scenario_sequence: Function to generate random sequences of scenarios """ import json import random FILM_SCENARIOS = { "openings": [ ("Dawn Patrol", "Character wakes up, morning routine reveals personality/situation"), ("The Arrival", "Protagonist enters new location for first time"), ("In Medias Res", "Opens mid-action, audience catches up"), ("The Funeral", "Character death sets story in motion, mourners gathered"), ("Voiceover Reflection", "Older character narrates past events"), ], "tension": [ ("The Ticking Clock", "Countdown visible/mentioned, deadline approaching"), ("Hiding in Plain Sight", "Character conceals identity among enemies"), ("The Stakeout", "Characters wait and watch from vehicle/building"), ("Parallel Editing Chase", "Cut between pursuer and pursued"), ("The Interrogation", "Character questioned under pressure"), ("Eavesdropping", "Character overhears crucial conversation"), ("The Setup/Double-Cross", "Trusted ally reveals betrayal"), ("Trapped in Enclosed Space", "Elevator, room, vehicle - no escape"), ("The Hostage Situation", "Loved one held, demands made"), ("Walking Into a Trap", "Audience knows danger character doesn't"), ], "action": [ ("The Standoff", "Multiple parties aim weapons, no one shoots first"), ("The Bar Fight", "Violence erupts in drinking establishment"), ("Car Chase Through City", "Vehicles weave through traffic, obstacles"), ("Rooftop Confrontation", "Final battle on building top, city below"), ("The Heist Execution", "Plan unfolds step by step with complications"), ("Training Montage", "Character improves skills over compressed time"), ("The Last Stand", "Outnumbered defenders hold position"), ("One vs Many", "Single fighter takes on multiple opponents"), ("The Duel", "Two opponents face off, formal or informal"), ("Escape Sequence", "Character flees captivity/danger"), ], "emotional": [ ("The Confession", "Character admits truth - love, crime, secret"), ("Deathbed Scene", "Dying character's final words/wishes"), ("The Reunion", "Long-separated characters meet again"), ("Breaking the News", "Character learns devastating information"), ("The Sacrifice", "Character gives up something precious for others"), ("Saying Goodbye", "Characters part ways, possibly forever"), ("The Breakdown", "Character's composure finally cracks"), ("Reconciliation", "Estranged characters make peace"), ("The Proposal", "Marriage or significant commitment offered"), ("Visiting the Grave", "Character speaks to deceased at burial site"), ], "discovery": [ ("Finding the Body", "Character discovers corpse"), ("The Evidence Room", "Character finds proof of conspiracy/truth"), ("Flashback Reveal", "Past event recontextualizes everything"), ("The Twist Revealed", "Major plot revelation changes understanding"), ("Reading the Letter/Document", "Written words deliver crucial info"), ("Surveillance Footage", "Character watches recording of key event"), ("The Photograph", "Image reveals connection or identity"), ("Decoding the Message", "Cipher/puzzle solved, meaning clear"), ], "social": [ ("The Dinner Party", "Tension beneath polite social gathering"), ("The Job Interview", "Character proves worth or fails to"), ("Meeting the Parents", "Romantic partner meets family"), ("The Courtroom", "Legal proceedings, testimony, verdict"), ("Press Conference", "Public statement, reporters' questions"), ("The Gala/Ball", "Formal event, everyone dressed up, intrigue"), ("The Wake/Reception", "Social gathering after significant event"), ], "endings": [ ("Walking Into the Sunset", "Hero departs, back to camera, horizon ahead"), ("The Circular Return", "Final scene mirrors opening, showing change"), ("Freeze Frame", "Action stops, often with voiceover or text"), ("The Bittersweet Victory", "Won but at great cost, hollow celebration"), ("New Dawn", "Sun rises on changed world/character, hope restored"), ("The Cliffhanger", "Unresolved tension, question left hanging"), ("Where Are They Now", "Text/montage showing characters' futures"), ("The Twist Ending", "Final revelation reframes entire story"), ("Full Circle Reunion", "Characters gather one last time"), ("The Long Walk Away", "Character leaves location, camera lingers"), ("Passing the Torch", "Legacy/knowledge transferred to next generation"), ("The Final Confrontation", "Last face-to-face with antagonist"), ("Quiet Moment After Storm", "Calm after climax, processing events"), ("The Sacrifice Payoff", "Earlier sacrifice proven worthwhile"), ("Open Road/New Beginning", "Character sets off on next journey"), ], } def generate_scenario_sequence(count, include_opening, include_tension, include_action, include_emotional, include_discovery, include_social, include_ending, force_opening, force_ending): """Generate a random sequence of film scenarios. Args: count: Number of scenarios to generate include_opening: Include opening scenarios include_tension: Include tension scenarios include_action: Include action scenarios include_emotional: Include emotional scenarios include_discovery: Include discovery scenarios include_social: Include social scenarios include_ending: Include ending scenarios force_opening: Force sequence to start with an opening force_ending: Force sequence to end with an ending Returns: Tuple of (list_output, json_output, prompts_output) """ available = [] if include_opening: available.extend([(s[0], s[1], "opening") for s in FILM_SCENARIOS["openings"]]) if include_tension: available.extend([(s[0], s[1], "tension") for s in FILM_SCENARIOS["tension"]]) if include_action: available.extend([(s[0], s[1], "action") for s in FILM_SCENARIOS["action"]]) if include_emotional: available.extend([(s[0], s[1], "emotional") for s in FILM_SCENARIOS["emotional"]]) if include_discovery: available.extend([(s[0], s[1], "discovery") for s in FILM_SCENARIOS["discovery"]]) if include_social: available.extend([(s[0], s[1], "social") for s in FILM_SCENARIOS["social"]]) if include_ending: available.extend([(s[0], s[1], "ending") for s in FILM_SCENARIOS["endings"]]) if not available: return "Select at least one category!", "{}", "" sequence = [] # Force opening if requested if force_opening and include_opening: opening = random.choice(FILM_SCENARIOS["openings"]) sequence.append((opening[0], opening[1], "opening")) count -= 1 # Force ending if requested ending_scene = None if force_ending and include_ending: ending_scene = random.choice(FILM_SCENARIOS["endings"]) count -= 1 # Fill middle with random selections middle_available = [s for s in available if s[2] not in (["opening"] if force_opening else []) and s[2] not in (["ending"] if force_ending else [])] if not middle_available: middle_available = available random.shuffle(middle_available) sequence.extend(middle_available[:max(0, count)]) # Add ending at the end if ending_scene: sequence.append((ending_scene[0], ending_scene[1], "ending")) # Format as list list_output = "## Generated Sequence\n\n" for i, (name, desc, cat) in enumerate(sequence, 1): list_output += f"**{i}. {name}** [{cat}]\n{desc}\n\n" # Format as config JSON (using correct engine format) config = {"story_location": {}} for i, (name, desc, cat) in enumerate(sequence, 1): state_name = name.lower().replace(" ", "_").replace("/", "_").replace("-", "_") current_state_id = f"scene_{i}_{state_name}" # Determine next state if i < len(sequence): next_name = sequence[i][0] # Get next scene's name next_state_name = next_name.lower().replace(" ", "_").replace("/", "_").replace("-", "_") next_state_id = f"scene_{i+1}_{next_state_name}" else: next_state_id = "ending" # Use proper format: choices as list of strings, transitions as dict config["story_location"][current_state_id] = { "description": f"[{cat.upper()}] {desc}", "media_prompt": f"Cinematic shot: {name} - {desc}", "choices": ["Continue"], "transitions": { "Continue": next_state_id } } # Add ending state first_state_name = sequence[0][0].lower().replace(" ", "_").replace("/", "_").replace("-", "_") config["story_location"]["ending"] = { "description": "The story concludes here.", "choices": ["Start Over"], "transitions": { "Start Over": f"scene_1_{first_state_name}" } } json_output = json.dumps(config, indent=2) # Format prompts only (for queue) prompts_output = "## Video Prompts (copy to queue)\n\n" for i, (name, desc, cat) in enumerate(sequence, 1): prompts_output += f"Cinematic shot: {name} - {desc}\n" return list_output, json_output, prompts_output