File size: 27,158 Bytes
243f369
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d55541a
d170586
243f369
 
 
 
 
d55541a
 
 
 
 
 
 
 
89cc3f0
 
243f369
 
 
 
ce0050d
 
 
243f369
 
d55541a
 
89cc3f0
d55541a
 
 
 
 
 
 
 
 
 
723fb80
 
ce0050d
723fb80
ce0050d
d55541a
723fb80
 
 
 
ce0050d
723fb80
ce0050d
 
723fb80
 
ce0050d
723fb80
ce0050d
243f369
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ce0050d
d92bbd4
 
 
 
ce0050d
243f369
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
import gradio as gr
import json
import os
import google.generativeai as genai

testgeminiapi = os.getenv("testgemini")
genai.configure(api_key=testgeminiapi)

configcomptestexample = {
  "village": {
    "start": {
      "description": "You wake up in a small village. You hear a rumor about a lost treasure.",
      "choices": [
        "explore village",
        "gather supplies",
        "rest"
      ],
      "transitions": {
        "explore village": "village_rumor",
        "gather supplies": "village_supplies",
        "rest": "village_start"
      },
      "consequences": {
        "gather supplies": {}
      },
      "media": []
    },
    "rumor": {
      "description": "You hear more details about the treasure hidden in the ancient ruins nearby.",
      "choices": [
        "decide to go",
        "ignore"
      ],
      "transitions": {
        "decide to go": "village_supplies",
        "ignore": "village_start"
      },
      "consequences": {
        "decide to go": {}
      },
      "media": []
    },
    "supplies": {
      "description": "You gather supplies for your journey.",
      "choices": [
        "head to forest",
        "stay in village"
      ],
      "transitions": {
        "head to forest": "forest_forest",
        "stay in village": "village_start"
      },
      "media": []
    }
  },
  "forest": {
    "forest": {
      "description": "You enter the dense forest, heading towards the ruins.",
      "choices": [
        "travel further",
        "return to village"
      ],
      "transitions": {
        "travel further": "ruins_ruins",
        "return to village": "village_start"
      },
      "media": []
    }
  },
  "ruins": {
    "ruins": {
      "description": "You reach the ancient ruins. The entrance is dark and eerie.",
      "choices": [
        "enter ruins",
        "return to forest"
      ],
      "transitions": {
        "enter ruins": "ruins_explore",
        "return to forest": "forest_forest"
      },
      "media": []
    },
    "explore": {
      "description": "You explore the ruins, encountering traps and puzzles.",
      "choices": [
        "solve puzzle",
        "avoid traps"
      ],
      "transitions": {
        "solve puzzle": "ruins_hiddenPassage",
        "avoid traps": "ruins_ruins"
      },
      "media": []
    },
    "hiddenPassage": {
      "description": "You solve a challenging puzzle and unlock a hidden passage.",
      "choices": [
        "enter passage",
        "go back"
      ],
      "transitions": {
        "enter passage": "ruins_treasureRoom",
        "go back": "ruins_explore"
      },
      "media": []
    },
    "treasureRoom": {
      "description": "You enter the treasure room and find the treasure chest.",
      "choices": [
        "take treasure",
        "leave"
      ],
      "transitions": {
        "take treasure": "ruins_celebrate",
        "leave": "ruins_ruins"
      },
      "consequences": {
        "take treasure": {}
      },
      "media": []
    },
    "celebrate": {
      "description": "You celebrate your discovery and decide to bring the treasure back to the village.",
      "choices": [
        "return to village"
      ],
      "transitions": {
        "return to village": "village_return"
      },
      "media": []
    }
  },
  "village_return": {
    "village_return": {
      "description": "You return to the village with the treasure and share it with the villagers.",
      "choices": [
        "end adventure"
      ],
      "transitions": {
        "end adventure": "end_end"
      },
      "media": []
    }
  },
  "end": {
    "end": {
      "description": "Your adventure ends here. The villagers are grateful and everyone's lives improve.",
      "choices": [],
      "transitions": {},
      "media": []
    }
  }
}


#------

# Create the model
generation_config = {
  "temperature": 1,
  "top_p": 0.95,
  "top_k": 64,
  "max_output_tokens": 8192,
  "response_mime_type": "text/plain",
}

modelpro = genai.GenerativeModel(
  model_name="gemini-1.5-pro",
  generation_config=generation_config,
  # safety_settings = Adjust safety settings
  # See https://ai.google.dev/gemini-api/docs/safety-settings
)

modelflash = genai.GenerativeModel(
  model_name="gemini-1.5-flash",
  generation_config=generation_config,
  # safety_settings = Adjust safety settings
  # See https://ai.google.dev/gemini-api/docs/safety-settings
)

def geminiproinferenceinstance(text):
    global modelpro
    chat_session = modelpro.start_chat(
      history=[
      ]
    )

    #response = chat_session.send_message(f"NBNB property name must be enclosed in double quotes. Use this as inspiration to make a pirate story aka keep same format to work with an existing app: /n/n{configcomptestexample} ")
    response = chat_session.send_message(text)
    
    return response.text #print(response.text)

def geminiflashinferenceinstance(text):
    global modelflash
    chat_session = modelflash.start_chat(
      history=[
      ]
    )

    #response = chat_session.send_message(f"NBNB property name must be enclosed in double quotes. Use this as inspiration to make a pirate story aka keep same format to work with an existing app: /n/n{configcomptestexample} ")
    response = chat_session.send_message(text)
    
    return response.text #print(response.text


#def brainstormconsiderations(text):
#    Finaloutput = geminiproinferenceinstance(text)

#    return Finaloutput

def generateconfig(text):
    prompt1 = "Please remix this to be about: ("
    prompt2 = """) - {"tavern": {"start": {"description": "You wake up in a dimly lit tavern, the smell of ale and salt heavy in the air. A grizzled sailor at the bar boasts about a hidden island overflowing with \"more gold than ye can dream of!\" ", "choices": ["approach sailor", "ignore sailor", "order grog"], "transitions": {"approach sailor": "tavern_rumor", "ignore sailor": "tavern_start", "order grog": "tavern_grog"}, "consequences": {}, "media": []}, "rumor": {"description": "The sailor, three sheets to the wind, spins a tale of treacherous waters, ancient curses, and a map hidden on a ghost ship. He claims to know the way.", "choices": ["offer to buy him another drink", "dismiss him as a drunkard"], "transitions": {"offer to buy him another drink": "tavern_map", "dismiss him as a drunkard": "tavern_start"}, "consequences": {}, "media": []}, "grog": {"description": "The tavern keeper slides you a tankard of potent grog. It burns pleasantly as it goes down, and you feel your senses dull.", "choices": ["order another", "eavesdrop on nearby pirates"], "transitions": {"order another": "tavern_grog", "eavesdrop on nearby pirates": "tavern_start"}, "media": []}, "map": {"description": "With a wink and a hiccup, the sailor produces a crumpled piece of parchment. It's stained with salt and what looks suspiciously like blood, but the markings... they resemble a map! ", "choices": ["propose a partnership", "try to buy the map", "steal the map"], "transitions": {"propose a partnership": "docks_prepare", "try to buy the map": "tavern_haggle", "steal the map": "tavern_fight"}, "consequences": {}, "media": []}, "haggle": {"description": "The sailor eyes you shrewdly. \"This here map's worth a king's ransom,\" he slurs.", "choices": ["offer a pouch of gold", "walk away"], "transitions": {"offer a pouch of gold": "docks_prepare", "walk away": "tavern_start"}, "consequences": {}, "media": []}, "fight": {"description": "You lunge for the map, but the sailor's quicker than he looks! A brawl erupts, tables are overturned, and mugs fly through the air.", "choices": ["fight dirty", "try to reason with him"], "transitions": {"fight dirty": "tavern_victory", "try to reason with him": "tavern_defeat"}, "consequences": {}, "media": []}, "victory": {"description": "With a final blow, you knock the sailor unconscious. You grab the map and make a hasty exit.", "choices": ["head to the docks"], "transitions": {"head to the docks": "docks_prepare"}, "consequences": {}, "media": []}, "defeat": {"description": "The sailor and a couple of his cronies land some solid punches. You're tossed out of the tavern, bruised and map-less.", "choices": ["nurse your wounds"], "transitions": {"nurse your wounds": "tavern_start"}, "consequences": {}, "media": []}}, "docks": {"prepare": {"description": "The salty air of the docks fills your lungs. You can practically taste the adventure on the horizon. But first, you need a ship and a crew...", "choices": ["find a ship", "assemble a crew"], "transitions": {"find a ship": "docks_ship", "assemble a crew": "docks_crew"}, "media": []}, "ship": {"description": "You spot a sturdy-looking galleon with a \"For Sale\" sign hanging precariously from its mast.", "choices": ["inspect the ship", "look for another vessel"], "transitions": {"inspect the ship": "docks_captain", "look for another vessel": "docks_prepare"}, "media": []}, "crew": {"description": "The docks are teeming with salty dogs of all shapes and sizes.", "choices": ["recruit seasoned sailors", "round up some desperate souls"], "transitions": {"recruit seasoned sailors": "docks_captain", "round up some desperate souls": "docks_captain"}, "consequences": {}, "media": []}, "captain": {"description": "With a ship and a crew (of varying competence), you're ready to set sail! ", "choices": ["set sail for the open sea!"], "transitions": {"set sail for the open sea!": "openSea_start"}, "media": []}}, "openSea": {"start": {"description": "The open sea stretches before you, vast and unforgiving. The wind whips at your sails as you set course for the uncharted waters where the treasure awaits.", "choices": ["consult the map", "enjoy the voyage"], "transitions": {"consult the map": "openSea_storm", "enjoy the voyage": "openSea_mutiny"}, "media": []}, "storm": {"description": "A storm gathers on the horizon, dark clouds swirling ominously. Waves crash against the hull, threatening to swallow you whole.", "choices": ["weather the storm", "change course"], "transitions": {"weather the storm": "openSea_ghostShip", "change course": "openSea_start"}, "media": []}, "mutiny": {"description": "Your crew, a motley bunch at best, begin to grumble. They're growing impatient and greedy, their eyes glinting with mutiny.", "choices": ["quell the mutiny", "reason with them"], "transitions": {"quell the mutiny": "openSea_ghostShip", "reason with them": "openSea_start"}, "consequences": {}, "media": []}, "ghostShip": {"description": "Through the mist and fog, a ghostly silhouette emerges. A ship, its sails in tatters, manned by skeletal figures. This... is the ghost ship.", "choices": ["board the ghost ship", "flee"], "transitions": {"board the ghost ship": "ghostShip_deck", "flee": "openSea_start"}, "media": []}}, "ghostShip": {"deck": {"description": "You step aboard the ghost ship, the air heavy with the stench of decay. Eerie silence hangs over the vessel.", "choices": ["explore the ship", "search for the captain's quarters"], "transitions": {"explore the ship": "ghostShip_brig", "search for the captain's quarters": "ghostShip_quarters"}, "media": []}, "brig": {"description": "You stumble upon the ship's brig, its cells still occupied by skeletal remains shackled to the walls.", "choices": ["examine the skeletons", "leave the brig"], "transitions": {"examine the skeletons": "ghostShip_clue", "leave the brig": "ghostShip_deck"}, "media": []}, "quarters": {"description": "The captain's quarters are in disarray, as if a struggle took place. A tattered journal lies open on the floor.", "choices": ["read the journal", "search for the map"], "transitions": {"read the journal": "ghostShip_clue", "search for the map": "ghostShip_treasure"}, "media": []}, "clue": {"description": "You piece together clues from the journal and the skeletons. The ghost ship's captain hid the real treasure map to protect it from mutineers.", "choices": ["continue searching"], "transitions": {"continue searching": "ghostShip_treasure"}, "media": []}, "treasure": {"description": "After careful searching, you find a hidden compartment behind a portrait. Inside, a gleaming treasure chest awaits!", "choices": ["open the chest", "take the chest and flee"], "transitions": {"open the chest": "ghostShip_victory", "take the chest and flee": "openSea_return"}, "consequences": {}, "media": []}, "victory": {"description": "The treasure chest overflows with gold, jewels, and artifacts beyond your wildest dreams! You've found the legendary pirate treasure!", "choices": ["claim your prize and set sail"], "transitions": {"claim your prize and set sail": "openSea_return"}, "consequences": {}, "media": []}}, "openSea_return": {"return": {"description": "With the treasure safely stowed on your own ship, you set sail for home, leaving the ghost ship to its eternal slumber.", "choices": ["sail into the sunset"], "transitions": {"sail into the sunset": "end_end"}, "media": []}}, "end": {"end": {"description": "The sun dips below the horizon, painting the sky in hues of gold and crimson. You've cheated death, outsmarted ghosts, and claimed a fortune in pirate treasure. Your legend will be sung in taverns for centuries to come.", "choices": [], "transitions": {}, "media": []}}}"""
    #Finaloutput =  geminiproinferenceinstance(f"NBNB property name must be enclosed in double quotes. Use this as inspiration to make a {text} (user requested) based story aka keep same format to work with an existing app: /n/n{configcomptestexample} ")
    Finaloutput =  geminiproinferenceinstance(prompt1 + text + prompt2)

    
    return Finaloutput

#def debugsuggestions(text):
#    Finaloutput = geminiproinferenceinstance(text)

#    return Finaloutput
    
#-----

# Define the states
all_states = {
    'village': {
        'start': {
            "description": "You wake up in a small village. You hear a rumor about a lost treasure.",
            "choices": ['explore village', 'gather supplies', 'rest'],
            "transitions": {'explore village': 'village_rumor', 'gather supplies': 'village_supplies', 'rest': 'village_start'},
            "consequences": {
                'gather supplies': lambda player: player.add_item('basic supplies')
            },
            "media": []
        },
        'rumor': {
            "description": "You hear more details about the treasure hidden in the ancient ruins nearby.",
            "choices": ['decide to go', 'ignore'],
            "transitions": {'decide to go': 'village_supplies', 'ignore': 'village_start'},
            "consequences": {
                'decide to go': lambda player: player.update_knowledge('treasure location')
            },
            "media": []
        },
        'supplies': {
            "description": "You gather supplies for your journey.",
            "choices": ['head to forest', 'stay in village'],
            "transitions": {'head to forest': 'forest_forest', 'stay in village': 'village_start'},
            "media": []
        },
    },
    'forest': {
        'forest': {
            "description": "You enter the dense forest, heading towards the ruins.",
            "choices": ['travel further', 'return to village'],
            "transitions": {'travel further': 'ruins_ruins', 'return to village': 'village_start'},
            "media": []
        },
    },
    'ruins': {
        'ruins': {
            "description": "You reach the ancient ruins. The entrance is dark and eerie.",
            "choices": ['enter ruins', 'return to forest'],
            "transitions": {'enter ruins': 'ruins_explore', 'return to forest': 'forest_forest'},
            "media": []
        },
        'explore': {
            "description": "You explore the ruins, encountering traps and puzzles.",
            "choices": ['solve puzzle', 'avoid traps'],
            "transitions": {'solve puzzle': 'ruins_hiddenPassage', 'avoid traps': 'ruins_ruins'},
            "media": []
        },
        'hiddenPassage': {
            "description": "You solve a challenging puzzle and unlock a hidden passage.",
            "choices": ['enter passage', 'go back'],
            "transitions": {'enter passage': 'ruins_treasureRoom', 'go back': 'ruins_explore'},
            "media": []
        },
        'treasureRoom': {
            "description": "You enter the treasure room and find the treasure chest.",
            "choices": ['take treasure', 'leave'],
            "transitions": {'take treasure': 'ruins_celebrate', 'leave': 'ruins_ruins'},
            "consequences": {
                'take treasure': lambda player: player.add_item('treasure')
            },
            "media": []
        },
        'celebrate': {
            "description": "You celebrate your discovery and decide to bring the treasure back to the village.",
            "choices": ['return to village'],
            "transitions": {'return to village': 'village_return'},
            "media": []
        },
    },
    'village_return': {
        'village_return': {
            "description": "You return to the village with the treasure and share it with the villagers.",
            "choices": ['end adventure'],
            "transitions": {'end adventure': 'end_end'},
            "media": []
        },
    },
    'end': {
        'end': {
            "description": "Your adventure ends here. The villagers are grateful and everyone's lives improve.",
            "choices": [],
            "transitions": {},
            "media": []
        },
    }
}

class Player:
    def __init__(self):
        self.inventory = []
        self.money = 20
        self.knowledge = {}

    def add_item(self, item):
        self.inventory.append(item)

    def has_item(self, item):
        return item in self.inventory

    def update_knowledge(self, topic):
        self.knowledge[topic] = True

#importing all_states from relatively_constant_variables

def validate_transitions(all_states):
    errors = []
    for location, states in all_states.items():
        for state_key, state in states.items():
            for transition_key, transition_state in state['transitions'].items():
                # Check if the transition is to another location
                if transition_state in all_states:
                    trans_location, trans_state = transition_state, 'start'  # Assuming 'start' state for new locations
                elif '_' in transition_state:
                    trans_location, trans_state = transition_state.split('_')
                else:
                    trans_location, trans_state = location, transition_state

                # Validate the transition state
                if trans_location not in all_states or trans_state not in all_states[trans_location]:
                    errors.append(f"Invalid transition from {location}.{state_key} to {trans_location}.{trans_state}")

    return errors

path_errors = validate_transitions(all_states)
if path_errors:
    for error in path_errors:
        print(error)
else:
    print("All transitions are valid.")

class GameSession:
    def __init__(self, starting_location='village', starting_state='start'):
        self.player = Player()
        self.current_location = starting_location
        self.current_state = starting_state
        self.game_log = []

    def make_choice(self, choice_index):
        state = all_states[self.current_location][self.current_state]
        if 0 <= choice_index < len(state['choices']):
            choice = state['choices'][choice_index]
            next_state = state['transitions'][choice]

            self.game_log.append(f"You chose: {choice}")
            self.game_log.append(state['description'])

            if 'consequences' in state and choice in state['consequences']:
              if state['consequences'][choice]:
                  state['consequences'][choice](self.player)
              else:
                  # Handle empty consequence, e.g., log a message or provide a default action
                  print(f"No consequence for choice: {choice}")
                  # You can add any default action here if needed

            if '_' in next_state:
                self.current_location, self.current_state = next_state.split('_')
            else:
                self.current_state = next_state

            return self.get_current_state_info()
        else:
            return "Invalid choice. Please try again."

    def get_current_state_info(self):
        state = all_states[self.current_location][self.current_state]
        choices = [f"{idx + 1}. {choice}" for idx, choice in enumerate(state['choices'])]
        return state['description'], choices, "\n".join(self.game_log)

    def get_current_state_media(self):
        media = all_states[self.current_location][self.current_state]['media']
        return media

def start_game(starting_location='village', starting_state='start'):
    game_session = GameSession(starting_location, starting_state)
    description, choices, game_log = game_session.get_current_state_info()
    return description, choices, game_log, game_session

def make_choice(choice, game_session, with_media=False): #Calls the nested make choice function in the game session class
    if not choice:
        description, choices, game_log = game_session.get_current_state_info()
        return description, choices, "Please select a choice before proceeding.", game_session

    choice_index = int(choice.split('.')[0]) - 1
    result = game_session.make_choice(choice_index)

    if with_media:
        media = game_session.get_current_state_media()
        return result[0], gr.update(choices=result[1]), result[2], game_session, media
    else:
        return result[0], gr.update(choices=result[1]), result[2], game_session

def load_game(custom_config=None, with_media=False):
    global all_states
    if not custom_config:
        return gr.update(value="No custom configuration provided."), None, None, None, None, None, None

    try:
        new_config = json.loads(custom_config)
        all_states = new_config

        # Determine the starting location and state
        starting_location = next(iter(all_states.keys()))
        starting_state = next(iter(all_states[starting_location].keys()))
        print(f"Starting location: {starting_location}, Starting state: {starting_state}")

        game_session = GameSession(starting_location, starting_state)
        description, choices, game_log = game_session.get_current_state_info()
        new_path_errors = validate_transitions(all_states)

        output_media = []

        if with_media:
            media_list = all_states[starting_location][starting_state].get('media', [])
            print(f"Media list: {media_list}")

            if media_list:
                for media_path in media_list:
                    #media_component = create_media_component(media_path)
                    output_media.append(media_path)
                print(f"Created {len(output_media)} media components")

        success_message = f"Custom configuration loaded successfully!\n{new_path_errors}"
        return (
            gr.update(value=success_message),
            game_log,
            description,
            gr.update(choices=choices),
            gr.update(value=custom_config),
            game_session,
            output_media if with_media else None
        )

    except json.JSONDecodeError as e:
        error_message = format_json_error(custom_config, e)
        return gr.update(value=error_message), None, None, None, None, gr.update(value=custom_config), None

    except Exception as e:
        error_message = f"Error loading custom configuration: {str(e)}"
        return gr.update(value=error_message), None, None, None, None, gr.update(value=custom_config), None

def format_json_error(config, error):
    lineno, colno = error.lineno, error.colno
    lines = config.split('\n')
    error_line = lines[lineno - 1] if lineno <= len(lines) else ""
    pointer = ' ' * (colno - 1) + '^'

    return f"""Invalid JSON format in custom configuration:
Error at line {lineno}, column {colno}:
{error_line}
{pointer}
Error details: {str(error)}"""

initgameinfo = start_game()

with gr.Blocks() as geminiapidemo:
    with gr.Tab("Generate and Debug"):
        #gr.Interface(brainstormconsiderations, inputs=["text"], outputs=["text"], description="some considerations for generated config")
        gr.Interface(generateconfig, inputs=["text"], outputs=["text"], description="Ask for a topic for gemini to write about config")
        #gr.Interface(debugsuggestions, inputs=["text"], outputs=["text"], description="debug generated config ")
        gr.Interface(geminiflashinferenceinstance, inputs=["text"], outputs=["text"], description="ask flash anything if pro is not available")
    with gr.Tab("Manual - Config With Assets"):
      gr.HTML("Placeholder as not complete yet (3D not supported, and time (esp need for audio)")
      with gr.Row():
          with gr.Column(scale=2):
              gr.Markdown("# Text-based Adventure Game")

              wadescription = gr.Textbox(label="Current Situation", lines=4, value=initgameinfo[0])
              wamediabool = gr.State(value=True)
              wamedia = gr.State(["testmedia/Stable Audio - Raindrops, output.wav"])

              @gr.render(inputs=wamedia)
              def dynamic_with_media(media_items):
                  print(media_items)
                  with gr.Group() as wamediagrouping:
                      gr.HTML("Placeholder to load all media tests - still need to test clearing media on ")
                      if media_items == []:
                          gr.Markdown("No media items to display.")
                      else:
                          for item in media_items:
                              render = create_media_component(item)

                  return wamediagrouping

              wachoices = gr.Radio(label="Your Choices", choices=initgameinfo[1])
              wasubmit_btn = gr.Button("Make Choice")
              wagame_log = gr.Textbox(label="Game Log", lines=20, value=initgameinfo[2])
              wagame_session = gr.State(value=initgameinfo[3])
              wasubmit_btn.click(
                  make_choice,
                  inputs=[wachoices, wagame_session, wamediabool],
                  outputs=[wadescription, wachoices, wagame_log, wagame_session, wamedia]
              )
          with gr.Column(scale=1):
              gr.Markdown("# Debugging")
              waerror_box = gr.Textbox(label="Path Errors", lines=4, value=path_errors)
              with gr.Accordion("Config (Game Spoiler and Example for llm to remix)", open=False):
                  wacustom_config = gr.Textbox(label="Custom Configuration (JSON)", value=json.dumps(all_states, default=lambda o: o.__dict__, indent=2), lines=8)
                  wacustom_configbtn = gr.Button("Load Custom Config")

                  wacustom_configbtn.click(
                      load_game,
                      inputs=[wacustom_config, wamediabool],
                      outputs=[waerror_box, wagame_log, wadescription, wachoices, wacustom_config, wagame_session, wamedia]
                  )

geminiapidemo.queue().launch()