Spaces:
Runtime error
Runtime error
| import random | |
| from relatively_constant_variables import player_engagement_items, story_events, all_idea_lists, existing_game_inspirations, multiplayer_features, list_names | |
| import json | |
| import gradio as gr | |
| import re | |
| import os | |
| def pick_random_items(items, n): | |
| return random.sample(items, n) | |
| def generate_timeline(events, label): | |
| timeline = [] | |
| for event in events: | |
| timeline.append((random.randint(1, 100), label, event)) | |
| return timeline | |
| def create_story(timeline): | |
| story = [] | |
| for entry in timeline: | |
| if entry[1] == "Story": | |
| story.append(f"The hero {entry[2].replace('engageBattle', 'engaged in a fierce battle').replace('solveRiddle', 'solved a complex riddle').replace('exploreLocation', 'explored a mysterious location')}.") | |
| else: | |
| story.append(f"The player interacted with {entry[2]}.") | |
| return " ".join(story) | |
| def generate_story_and_timeline(no_story_timeline_points=10, no_ui_timeline_points=10, num_lists=1, items_per_list=1, include_existing_games=False, include_multiplayer=False): # , no_media_timeline_points=5, include_media=True): | |
| # Pick 10 random UI items | |
| random_ui_items = pick_random_items(player_engagement_items, no_ui_timeline_points) | |
| random_story_items = pick_random_items(story_events, no_story_timeline_points) | |
| # Generate UI and story timelines | |
| ui_timeline = generate_timeline(random_ui_items, "UI") | |
| story_timeline = generate_timeline(random_story_items, "Story") | |
| # Initialize merged timeline with UI and story timelines | |
| merged_timeline = ui_timeline + story_timeline | |
| #no_media_merged_timeline = ui_timeline + story_timeline | |
| #print(merged_timeline) | |
| #print(no_media_merged_timeline) | |
| # Include media-related items if specified | |
| # if include_media: | |
| # media_files = generate_media_file_list(no_media_timeline_points) | |
| # #rendered_media = render_media_with_dropdowns(media_files) | |
| # media_timeline = generate_timeline(media_files, "Media") | |
| # merged_timeline += media_timeline | |
| # print(merged_timeline) | |
| # Sort the merged timeline based on the random numbers | |
| merged_timeline.sort(key=lambda x: x[0]) | |
| # no_media_merged_timeline.sort(key=lambda x: x[0]) | |
| # Create the story | |
| story = create_story(merged_timeline) | |
| # Format the timeline for display | |
| formatted_timeline = "\n".join([f"{entry[0]}: {entry[1]} - {entry[2]}" for entry in merged_timeline]) | |
| # no_media_formatted_timeline = "\n".join([f"{entry[0]}: {entry[1]} - {entry[2]}" for entry in no_media_merged_timeline]) | |
| # game_structure_with_media = generate_game_structures(formatted_timeline) #, game_structure_without_media = generate_game_structures(formatted_timeline, no_media_formatted_timeline) | |
| game_structure_with_media = convert_timeline_to_game_structure(formatted_timeline) | |
| print("simulplay debug - good to here 4") | |
| suggestions, selected_list_names = timeline_get_random_suggestions(num_lists, items_per_list, include_existing_games, include_multiplayer) | |
| print("simulplay debug - good to here 4") | |
| return formatted_timeline, story, json.dumps(game_structure_with_media, indent=2), suggestions, selected_list_names #no_media_formatted_timeline, json.dumps(game_structure_without_media, indent=2) #, game_structure_with_media | |
| media_file_types = ["image", "video", "audio"] | |
| def generate_media_file_list(n): | |
| return [random.choice(media_file_types) for _ in range(n)] | |
| def show_elements(text): | |
| # Parse the input text | |
| pattern = r'(\d+): (UI|Story|Media) - (.+)' | |
| blocks = re.findall(pattern, text) | |
| # Sort blocks by their timestamp | |
| blocks.sort(key=lambda x: int(x[0])) | |
| outputs = [] | |
| for timestamp, block_type, content in blocks: | |
| if block_type == 'UI': | |
| # Create HTML for UI elements | |
| ui_html = f'<div class="ui-element">{content}</div>' | |
| outputs.append(gr.HTML(ui_html)) | |
| elif block_type == 'Story': | |
| # Display story elements as Markdown | |
| outputs.append(gr.Markdown(f"**{content}**")) | |
| elif block_type == 'Media': | |
| if content.lower() == 'audio': | |
| # Placeholder for audio element | |
| outputs.append(gr.Audio(label=f"Audio at {timestamp} in the order")) | |
| elif content.lower() == 'video': | |
| # Placeholder for video element | |
| outputs.append(gr.Video(label=f"Video at {timestamp} in the order")) | |
| elif content.lower() == 'image': | |
| # Placeholder for image element | |
| outputs.append(gr.Image(label=f"Image at {timestamp} in the order")) | |
| return outputs | |
| def show_elements_json_input(json_input): | |
| data = json.loads(json_input) | |
| masterlocation1 = data['masterlocation1'] | |
| outputs = [] | |
| for location, details in masterlocation1.items(): | |
| if location == 'end': | |
| continue | |
| with gr.Accordion(f"Location: {location} - Previous description {details['description']}", open=False): | |
| description = gr.Textbox(label="Description", value=details['description'], interactive=True) | |
| outputs.append(description) | |
| events = gr.Textbox(label="Events", value=json.dumps(details['events']), interactive=True) | |
| outputs.append(events) | |
| choices = gr.Textbox(label="Choices", value=json.dumps(details['choices']), interactive=True) | |
| outputs.append(choices) | |
| transitions = gr.Textbox(label="Transitions", value=json.dumps(details['transitions']), interactive=True) | |
| outputs.append(transitions) | |
| # New media field | |
| media = gr.Textbox(label="Media", value=json.dumps(details['media']), interactive=True) | |
| outputs.append(media) | |
| # New developernotes field | |
| developernotes = gr.Textbox(label="developernotes", value=json.dumps(details['developernotes']), interactive=True) | |
| outputs.append(developernotes) | |
| #adding/removing a field means incrementing/decreasing the i+n to match the fields | |
| num_current_unique_fields = 6 | |
| def update_json(*current_values): | |
| updated_data = {"masterlocation1": {}} | |
| locations = [loc for loc in masterlocation1.keys() if loc != 'end'] | |
| for i, location in enumerate(locations): | |
| updated_data["masterlocation1"][location] = { | |
| "description": current_values[i*num_current_unique_fields], | |
| "events": json.loads(current_values[i*num_current_unique_fields + 1]), | |
| "choices": json.loads(current_values[i*num_current_unique_fields + 2]), | |
| "transitions": json.loads(current_values[i*num_current_unique_fields + 3]), | |
| "media": json.loads(current_values[i*num_current_unique_fields + 4]), # New media field | |
| "developernotes": json.loads(current_values[i*num_current_unique_fields + 5]) | |
| } | |
| updated_data["masterlocation1"]["end"] = masterlocation1["end"] | |
| return json.dumps(updated_data, indent=2) #json.dumps(updated_data, default=lambda o: o.__dict__, indent=2) | |
| update_button = gr.Button("Update JSON - Still need to copy to correct textbox to load") | |
| json_output = gr.Textbox(label="Updated JSON - Still need to copy to correct textbox to load", lines=10) | |
| #json_output = gr.Code(label="Updated JSON", lines=10) #Locks whole UI so use textbox | |
| update_button.click(update_json, inputs=outputs, outputs=json_output) | |
| return outputs + [update_button, json_output] #, json_output_code] | |
| def show_elements_json_input_play_and_edit_version(json_input): | |
| data = json.loads(json_input) | |
| outputs = [] | |
| for location_name, location_data in data.items(): | |
| if location_name == "end": | |
| continue | |
| for sub_location, details in location_data.items(): | |
| with gr.Accordion(f"Location: {location_name} - {sub_location}", open=False): | |
| description = gr.Textbox(label="Description", value=details.get('description', ''), interactive=True) | |
| outputs.append(description) | |
| choices = gr.Textbox(label="Choices", value=json.dumps(details.get('choices', [])), interactive=True) | |
| outputs.append(choices) | |
| transitions = gr.Textbox(label="Transitions", value=json.dumps(details.get('transitions', {})), interactive=True) | |
| outputs.append(transitions) | |
| consequences = gr.Textbox(label="Consequences", value=json.dumps(details.get('consequences', {})), interactive=True) | |
| outputs.append(consequences) | |
| media = gr.Textbox(label="Media", value=json.dumps(details.get('media', [])), interactive=True) | |
| outputs.append(media) | |
| # Add developernotes field if it exists in the config | |
| if 'developernotes' in details: | |
| developernotes = gr.Textbox(label="Developer Notes", value=details.get('developernotes', ''), interactive=True) | |
| outputs.append(developernotes) | |
| # Determine the number of fields dynamically | |
| num_current_unique_fields = 5 if 'developernotes' not in next(iter(next(iter(data.values())).values())) else 6 | |
| def update_json(*current_values): | |
| updated_data = {} | |
| location_names = list(data.keys()) | |
| location_names.remove("end") if "end" in location_names else None | |
| value_index = 0 | |
| for location_name in location_names: | |
| updated_data[location_name] = {} | |
| sub_locations = list(data[location_name].keys()) | |
| for sub_location in sub_locations: | |
| updated_data[location_name][sub_location] = { | |
| "description": current_values[value_index], | |
| "choices": json.loads(current_values[value_index + 1]), | |
| "transitions": json.loads(current_values[value_index + 2]), | |
| "consequences": json.loads(current_values[value_index + 3]), | |
| "media": json.loads(current_values[value_index + 4]) | |
| } | |
| if num_current_unique_fields == 6: | |
| updated_data[location_name][sub_location]["developernotes"] = current_values[value_index + 5] | |
| value_index += num_current_unique_fields | |
| if "end" in data: | |
| updated_data["end"] = data["end"] | |
| return json.dumps(updated_data, indent=2) | |
| update_button = gr.Button("Update JSON") | |
| json_output = gr.Textbox(label="Updated JSON", lines=10) | |
| update_button.click(update_json, inputs=outputs, outputs=json_output) | |
| return outputs + [update_button, json_output] | |
| def create_media_component(file_path): | |
| print(file_path) | |
| _, extension = os.path.splitext(file_path) | |
| extension = extension.lower()[1:] # Remove the dot and convert to lowercase | |
| if extension in ['jpg', 'jpeg', 'png', 'gif', 'webp']: | |
| return gr.Image(value=file_path, label="Image Input") | |
| elif extension in ['mp4', 'avi', 'mov']: | |
| return gr.Video(value=file_path, label="Video Input") | |
| elif extension in ['mp3', 'wav', 'ogg']: | |
| return gr.Audio(value=file_path, label="Audio Input") | |
| else: | |
| return gr.Textbox(value=file_path, label=f"File: {os.path.basename(file_path)}") | |
| def convert_timeline_to_game_structure(timeline): | |
| lines = timeline.split('\n') | |
| game_structure = {} | |
| current_location = 0 | |
| sub_location = 0 | |
| for i, line in enumerate(lines): | |
| if line.strip() == "": | |
| continue | |
| if line[0].isdigit(): # New location starts | |
| current_location += 1 | |
| sub_location = 0 | |
| location_key = f"location{current_location}" | |
| game_structure[location_key] = { | |
| "description": "", | |
| "events": [], | |
| "choices": ["continue"], | |
| "transitions": {}, | |
| "media": [], | |
| "developernotes": [] | |
| } | |
| else: # Continue with sub-locations or media entries | |
| sub_location += 1 | |
| location_key = f"location{current_location}_{sub_location}" | |
| # Extract the event description | |
| parts = line.split(': ', 1) | |
| if len(parts) == 2: | |
| prefix, rest = parts | |
| event_parts = rest.split(' - ', 1) | |
| if len(event_parts) == 2: | |
| event_type, event_description = event_parts | |
| else: | |
| event_type, event_description = "Unknown", rest | |
| else: | |
| event_type, event_description = "Unknown", line | |
| description = rest.strip() if event_type in ["Media", "UI"] else f"{event_type}: {event_description}" | |
| if sub_location == 0: | |
| game_structure[f"location{current_location}"]["description"] = description | |
| else: | |
| game_structure[f"location{current_location}"]["events"].append({ | |
| "description": description, | |
| "type": event_type | |
| }) | |
| # Set the transition to the next location or to the end | |
| if i < len(lines) - 1: | |
| next_line = lines[i + 1].strip() | |
| if next_line and next_line[0].isdigit(): # New location starts | |
| game_structure[f"location{current_location}"]["transitions"]["continue"] = f"masterlocation1_location{current_location + 1}" | |
| else: | |
| #game_structure[f"location{current_location}"]["transitions"]["continue"] = f"location_{current_location}_{sub_location + 1}" | |
| game_structure[f"location{current_location}"]["transitions"]["continue"] = "end" | |
| else: | |
| game_structure[f"location{current_location}"]["transitions"]["continue"] = "end" | |
| # Add an end location | |
| game_structure["end"] = { | |
| "description": "The adventure ends here.", | |
| # "choices": [], | |
| # "transitions": {} | |
| "choices": ["restart"], | |
| "transitions": {"restart": "location1"} # Assuming location_1 is the start | |
| } | |
| # Wrap the game structure in master_location1 | |
| wrapped_structure = {"masterlocation1": game_structure} | |
| return wrapped_structure | |
| # def generate_game_structures(timeline_with_media): #, timeline_without_media): | |
| # game_structure_with_media = convert_timeline_to_game_structure(timeline_with_media) | |
| # #game_structure_without_media = convert_timeline_to_game_structure(timeline_without_media) | |
| # return game_structure_with_media #, game_structure_without_media | |
| # def timeline_get_random_suggestions(num_lists, items_per_list): | |
| # """ | |
| # Generate random suggestions from a specified number of lists. | |
| # :param num_lists: Number of lists to consider | |
| # :param items_per_list: Number of items to select from each list | |
| # :return: A list of randomly selected suggestions | |
| # """ | |
| # selected_lists = random.sample(all_idea_lists, min(num_lists, len(all_idea_lists))) | |
| # suggestions = [] | |
| # for lst in selected_lists: | |
| # suggestions.extend(random.sample(lst, min(items_per_list, len(lst)))) | |
| # return suggestions | |
| def timeline_get_random_suggestions(num_lists, items_per_list, include_existing_games, include_multiplayer): | |
| """ | |
| Generate random suggestions from a specified number of lists. | |
| :param num_lists: Number of lists to consider | |
| :param items_per_list: Number of items to select from each list | |
| :param include_existing_games: Whether to include existing game inspiration lists | |
| :param include_multiplayer: Whether to include multiplayer features list | |
| :return: A tuple containing the list of randomly selected suggestions and the names of selected lists | |
| """ | |
| available_lists = all_idea_lists.copy() | |
| if not include_existing_games: | |
| available_lists = [lst for lst in available_lists if lst not in existing_game_inspirations] | |
| if not include_multiplayer: | |
| available_lists = [lst for lst in available_lists if lst != multiplayer_features] | |
| selected_lists = random.sample(available_lists, min(num_lists, len(available_lists))) | |
| suggestions = [] | |
| selected_list_names = [] | |
| for lst in selected_lists: | |
| suggestions.extend(random.sample(lst, min(items_per_list, len(lst)))) | |
| selected_list_names.append(list_names[all_idea_lists.index(lst)]) | |
| return suggestions, selected_list_names |