sunbal7 commited on
Commit
d560106
·
verified ·
1 Parent(s): 4d2a237

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -2390
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py - Game-Based Learning Version
2
  import streamlit as st
3
  import os
4
  import time
@@ -10,7 +10,6 @@ import re
10
  from PIL import Image
11
  import io
12
  import matplotlib.pyplot as plt
13
- from groq import Groq
14
  from transformers import pipeline
15
  import torch
16
 
@@ -252,13 +251,14 @@ CONCEPTS = {
252
  }
253
  }
254
 
255
- # Initialize Groq client
256
- def get_groq_client():
 
 
257
  try:
258
- # Use a free proxy for Groq API access
259
- return Groq(api_key="free-proxy-key", base_url="https://api.groq.com/openai/v1")
260
  except:
261
- st.error("Could not initialize Groq client. Using fallback method.")
262
  return None
263
 
264
  # Analyze story and extract concepts
@@ -289,43 +289,11 @@ def analyze_story(story):
289
 
290
  return list(set(detected_concepts))
291
 
292
- # Generate game scenario using Groq
293
  def generate_game_scenario(story, concepts):
294
  """Generate a game scenario based on the story and concepts"""
295
  try:
296
- # Use Groq API for fast response
297
- client = get_groq_client()
298
- if client:
299
- system_prompt = (
300
- "You are an expert in creating educational games for children. "
301
- "Create a simple 3D game scenario based on the child's story. "
302
- "The game should teach programming concepts through gameplay. "
303
- "Structure your response with:\n"
304
- "Game Title: ...\n"
305
- "Game Objective: ...\n"
306
- "Characters: ...\n"
307
- "Game Mechanics: ...\n"
308
- "Coding Concepts: Explain how these programming concepts are used: " + ", ".join(concepts) + "\n"
309
- "Visual Description: Describe the game world visually\n"
310
- "Keep it under 200 words and suitable for children aged 6-12."
311
- )
312
-
313
- response = client.chat.completions.create(
314
- model="llama3-70b-8192",
315
- messages=[
316
- {"role": "system", "content": system_prompt},
317
- {"role": "user", "content": story}
318
- ],
319
- temperature=0.7,
320
- max_tokens=500
321
- )
322
- return response.choices[0].message.content
323
- except Exception as e:
324
- st.error(f"Groq API error: {str(e)}")
325
-
326
- # Fallback to Hugging Face model
327
- try:
328
- generator = pipeline("text-generation", model="HuggingFaceH4/zephyr-7b-beta")
329
  prompt = (
330
  f"Create a children's educational game based on this story: {story}\n"
331
  f"Game should teach these programming concepts: {', '.join(concepts)}\n"
@@ -337,50 +305,59 @@ def generate_game_scenario(story, concepts):
337
  "Coding Concepts: ...\n"
338
  "Visual Description: ...\n"
339
  )
340
- result = generator(prompt, max_length=400, do_sample=True, temperature=0.7)
341
- return result[0]['generated_text']
342
- except:
343
- # Final fallback
344
- return (
345
- f"Game Title: {story[:20]} Adventure\n"
346
- f"Game Objective: Complete challenges based on the story: {story[:100]}...\n"
347
- "Characters: Hero character based on the story\n"
348
- "Game Mechanics: Navigate through levels, collect items, solve puzzles\n"
349
- f"Coding Concepts: This game teaches {', '.join(concepts)} through gameplay\n"
350
- "Visual Description: Colorful 3D world with characters and obstacles"
351
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
352
 
353
  # Generate game code explanation
354
  def generate_game_explanation(story, concepts, game_scenario):
355
  """Generate explanation of game code"""
356
  try:
357
- client = get_groq_client()
358
- if client:
359
- system_prompt = (
360
- "Explain how the game code implements the programming concepts in a way "
361
- "a child can understand. Use simple analogies and relate to the story. "
362
- "Structure your response with:\n"
363
- "Introduction: ...\n"
364
- "Concept 1: ...\n"
365
- "Concept 2: ...\n"
366
- "Conclusion: ...\n"
367
- "Keep it under 300 words and fun for kids."
368
- )
369
-
370
- response = client.chat.completions.create(
371
- model="llama3-70b-8192",
372
- messages=[
373
- {"role": "system", "content": system_prompt},
374
- {"role": "user", "content": f"Story: {story}\nGame Scenario: {game_scenario}\nConcepts: {', '.join(concepts)}"}
375
- ],
376
  temperature=0.7,
377
- max_tokens=600
378
  )
379
- return response.choices[0].message.content
380
  except:
381
  pass
382
 
383
- # Fallback
384
  concept_explanations = "\n".join(
385
  [f"- {CONCEPTS[c]['name']}: {CONCEPTS[c]['game_example']}" for c in concepts]
386
  )
@@ -393,7 +370,22 @@ def generate_game_explanation(story, concepts, game_scenario):
393
  # Generate simple game code
394
  def generate_game_code(story, concepts):
395
  """Generate simple PyGame code for the game"""
396
- # This is a template - in a real app, this would be dynamically generated
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
  return f"""
398
  # {story[:30]} Adventure Game
399
  import pygame
@@ -492,2318 +484,9 @@ while running:
492
  score_text = font.render(f"Stars: {{score}}", True, (0, 0, 0))
493
  screen.blit(score_text, (20, 20))
494
 
495
- # Update display
496
- pygame.display.flip()
497
- clock.tick(60)
498
-
499
- pygame.quit()
500
- """
501
-
502
- # Generate game preview visualization
503
- def generate_game_preview(game_scenario):
504
- """Generate a visual preview of the game"""
505
- try:
506
- # Extract title from game scenario
507
- title_match = re.search(r"Game Title: (.+)", game_scenario)
508
- title = title_match.group(1) if title_match else "Your Adventure"
509
-
510
- # Create a simple visualization
511
- fig, ax = plt.subplots(figsize=(10, 6))
512
- ax.set_facecolor('#a2d2ff')
513
- ax.set_xlim(0, 10)
514
- ax.set_ylim(0, 6)
515
-
516
- # Draw game elements
517
- ax.text(5, 5, title, fontsize=20, ha='center', color='#9b5de5')
518
- ax.plot([1, 9], [3, 3], 'k-', linewidth=2) # Ground
519
-
520
- # Player character
521
- ax.plot(2, 3.5, 'ro', markersize=15)
522
-
523
- # Goal
524
- ax.plot(8, 3.5, 'go', markersize=15)
525
-
526
- # Obstacles
527
- for i in range(3):
528
- x = random.uniform(3, 7)
529
- y = random.uniform(3.2, 4)
530
- ax.plot(x, y, 's', color='#8d99ae', markersize=12)
531
-
532
- # Path
533
- ax.plot([2, 8], [3.5, 3.5], 'y--', linewidth=2)
534
-
535
- ax.axis('off')
536
- ax.set_title("Game Preview", fontsize=16)
537
-
538
- # Save to bytes
539
- buf = io.BytesIO()
540
- plt.savefig(buf, format='png', dpi=100, bbox_inches='tight')
541
- buf.seek(0)
542
- return buf
543
- except:
544
- return None
545
-
546
- # Main application function
547
- def main():
548
- init_session_state()
549
-
550
- st.title("🎮 StoryCoder - Learn Coding Through Games!")
551
- st.subheader("Turn your story into a 3D game and discover coding secrets!")
552
-
553
- # Create tabs
554
- st.markdown('<div class="tabs">', unsafe_allow_html=True)
555
- col1, col2, col3, col4, col5 = st.columns(5)
556
- with col1:
557
- if st.button("📖 Create Story", use_container_width=True):
558
- st.session_state.active_tab = "story"
559
- with col2:
560
- if st.button("🎮 Play Game", use_container_width=True):
561
- st.session_state.active_tab = "game"
562
- with col3:
563
- if st.button("🔍 Concepts", use_container_width=True):
564
- st.session_state.active_tab = "concepts"
565
- with col4:
566
- if st.button("💻 Game Code", use_container_width=True):
567
- st.session_state.active_tab = "code"
568
- with col5:
569
- if st.button("🔄 New Story", use_container_width=True):
570
- st.session_state.story = ""
571
- st.session_state.concepts = []
572
- st.session_state.game_scenario = ""
573
- st.session_state.game_code = ""
574
- st.session_state.game_explanation = ""
575
- st.session_state.game_preview = ""
576
- st.session_state.active_tab = "story"
577
- st.markdown('</div>', unsafe_allow_html=True)
578
-
579
- # Story creation tab
580
- if st.session_state.active_tab == "story":
581
- with st.container():
582
- st.header("📖 Create Your Story")
583
- st.write("Write a short story (2-5 sentences) and I'll turn it into a 3D game!")
584
-
585
- story = st.text_area(
586
- "Your story:",
587
- height=200,
588
- placeholder="Once upon a time, a brave knight had to collect 5 magical stars in a castle...",
589
- value=st.session_state.story,
590
- key="story_input"
591
- )
592
-
593
- if st.button("Create Game!", use_container_width=True):
594
- if len(story) < 10:
595
- st.error("Your story needs to be at least 10 characters long!")
596
- else:
597
- st.session_state.story = story
598
- st.session_state.loading = True
599
-
600
- with st.spinner("🧠 Analyzing your story for coding concepts..."):
601
- st.session_state.concepts = analyze_story(story)
602
-
603
- with st.spinner("🎮 Creating your 3D game scenario..."):
604
- st.session_state.game_scenario = generate_game_scenario(
605
- story, st.session_state.concepts
606
- )
607
-
608
- with st.spinner("💻 Generating game code..."):
609
- st.session_state.game_code = generate_game_code(
610
- story, st.session_state.concepts
611
- )
612
-
613
- with st.spinner("📚 Creating coding explanations..."):
614
- st.session_state.game_explanation = generate_game_explanation(
615
- story, st.session_state.concepts, st.session_state.game_scenario
616
- )
617
-
618
- with st.spinner("🖼️ Generating game preview..."):
619
- preview = generate_game_preview(st.session_state.game_scenario)
620
- if preview:
621
- st.session_state.game_preview = preview
622
-
623
- st.session_state.active_tab = "game"
624
- st.session_state.loading = False
625
- st.rerun()
626
-
627
- # Show examples
628
- st.subheader("✨ Story Examples")
629
- col1, col2, col3 = st.columns(3)
630
- with col1:
631
- st.caption("Space Explorer")
632
- st.code('"An astronaut needs to collect 3 stars while avoiding asteroids"', language="text")
633
- st.image("https://i.imgur.com/7zQY1eE.gif",
634
- use_column_width=True,
635
- caption="Space Explorer Game")
636
- with col2:
637
- st.caption("Jungle Adventure")
638
- st.code('"A monkey swings through trees to collect bananas before sunset"', language="text")
639
- st.image("https://i.imgur.com/5X8jYAy.gif",
640
- use_column_width=True,
641
- caption="Jungle Adventure Game")
642
- with col3:
643
- st.caption("Dragon Quest")
644
- st.code('"A dragon flies through clouds to collect magic crystals"', language="text")
645
- st.image("https://i.imgur.com/9zJkQ7P.gif",
646
- use_column_width=True,
647
- caption="Dragon Quest Game")
648
-
649
- # Game tab
650
- elif st.session_state.active_tab == "game":
651
- st.header("🎮 Your Story Game")
652
-
653
- if not st.session_state.story:
654
- st.warning("Please create a story first!")
655
- st.session_state.active_tab = "story"
656
- st.rerun()
657
-
658
- # Display game scenario
659
- st.subheader("🌟 Game Scenario")
660
- st.markdown(f'<div class="game-card">{st.session_state.game_scenario}</div>', unsafe_allow_html=True)
661
-
662
- # Display game preview
663
- st.subheader("🖼️ Game Preview")
664
- if st.session_state.game_preview:
665
- st.image(st.session_state.game_preview, use_container_width=True)
666
- else:
667
- st.warning("Game preview couldn't be generated. Showing example instead.")
668
- st.image("https://i.imgur.com/7zQY1eE.gif", use_container_width=True)
669
-
670
- # Game explanation
671
- st.subheader("📚 How This Game Teaches Coding")
672
- st.markdown(f'<div class="game-card">{st.session_state.game_explanation}</div>', unsafe_allow_html=True)
673
-
674
- # Play instructions
675
- st.subheader("▶️ How to Play")
676
- st.markdown("""
677
- <div class="game-card">
678
- <ol>
679
- <li>Download the game code from the <b>Game Code</b> tab</li>
680
- <li>Install Python from <a href="https://python.org">python.org</a></li>
681
- <li>Install PyGame: <code>pip install pygame</code></li>
682
- <li>Run the game: <code>python your_game.py</code></li>
683
- <li>Use arrow keys to move your character!</li>
684
- </ol>
685
- </div>
686
- """, unsafe_allow_html=True)
687
-
688
- if st.button("Learn Coding Concepts", use_container_width=True):
689
- st.session_state.active_tab = "concepts"
690
- st.rerun()
691
-
692
- # Concepts tab
693
- elif st.session_state.active_tab == "concepts":
694
- st.header("🔍 Coding Concepts in Your Game")
695
- st.subheader("Your game teaches these programming concepts:")
696
-
697
- if not st.session_state.concepts:
698
- st.warning("No concepts detected in your story! Try adding words like '3 times', 'if', or 'collect'.")
699
- else:
700
- for concept in st.session_state.concepts:
701
- if concept in CONCEPTS:
702
- details = CONCEPTS[concept]
703
- st.markdown(f"""
704
- <div class="concept-card" style="border-left: 5px solid {details['color']};">
705
- <div style="display:flex; align-items:center; gap:15px;">
706
- <span style="font-size:36px;">{details['emoji']}</span>
707
- <h3 style="color:{details['color']};">{details['name']}</h3>
708
- </div>
709
- <p>{details['description']}</p>
710
- <p><b>In your game:</b> {details['game_example']}</p>
711
- <pre style="background:#f0f0f0; padding:10px; border-radius:8px;">{details['example']}</pre>
712
- </div>
713
- """, unsafe_allow_html=True)
714
-
715
- if st.button("See the Game Code", use_container_width=True):
716
- st.session_state.active_tab = "code"
717
- st.rerun()
718
-
719
- # Code tab
720
- elif st.session_state.active_tab == "code":
721
- st.header("💻 Game Code")
722
- st.write("Here's the Python code for your game. Download it and run on your computer!")
723
-
724
- if st.session_state.game_code:
725
- # Display code with syntax highlighting
726
- st.subheader("Your Game Code")
727
- st.code(st.session_state.game_code, language="python")
728
-
729
- # Download button
730
- st.download_button(
731
- label="📥 Download Game Code",
732
- data=st.session_state.game_code,
733
- file_name="story_game.py",
734
- mime="text/python",
735
- use_container_width=True
736
- )
737
-
738
- # Game running instructions
739
- st.subheader("🖥️ How to Run Your Game")
740
- st.markdown("""
741
- <div class="game-card">
742
- <ol>
743
- <li>Install Python from <a href="https://python.org">python.org</a></li>
744
- <li>Install PyGame: Open command prompt and type <code>pip install pygame</code></li>
745
- <li>Save the game code to a file named <code>my_game.py</code></li>
746
- <li>Run the game: <code>python my_game.py</code></li>
747
- <li>Use arrow keys to play!</li>
748
- </ol>
749
- </div>
750
- """, unsafe_allow_html=True)
751
-
752
- # What to expect
753
- st.subheader("🎮 What to Expect When Playing")
754
- st.markdown("""
755
- <div class="game-card">
756
- <ul>
757
- <li>Move your character (red square) with arrow keys</li>
758
- <li>Collect the green stars to increase your score</li>
759
- <li>Avoid the brown obstacles</li>
760
- <li>See how programming concepts make the game work!</li>
761
- </ul>
762
- </div>
763
- """, unsafe_allow_html=True)
764
- else:
765
- st.warning("No game code generated yet!")
766
-
767
- if st.button("Create Another Story!", use_container_width=True):
768
- st.session_state.active_tab = "story"
769
- st.rerun()
770
-
771
- if __name__ == "__main__":
772
- main()# app.py - Game-Based Learning Version
773
- import streamlit as st
774
- import os
775
- import time
776
- import random
777
- import json
778
- import base64
779
- import requests
780
- import re
781
- from PIL import Image
782
- import io
783
- import matplotlib.pyplot as plt
784
- from groq import Groq
785
- from transformers import pipeline
786
- import torch
787
-
788
- # Configure Streamlit page
789
- st.set_page_config(
790
- page_title="StoryCoder - Learn Coding Through Games",
791
- page_icon="🎮",
792
- layout="wide",
793
- initial_sidebar_state="expanded"
794
- )
795
-
796
- # Custom CSS for game-themed UI
797
- st.markdown("""
798
- <style>
799
- @import url('https://fonts.googleapis.com/css2?family=Fredoka+One&family=Comic+Neue:wght@700&display=swap');
800
-
801
- :root {
802
- --primary: #FF6B6B;
803
- --secondary: #4ECDC4;
804
- --accent: #FFD166;
805
- --dark: #1A535C;
806
- --light: #F7FFF7;
807
- --game-blue: #118AB2;
808
- --game-purple: #9B5DE5;
809
- }
810
-
811
- body {
812
- background: linear-gradient(135deg, #E8F4F8 0%, #FFDEE9 100%);
813
- font-family: 'Comic Neue', cursive;
814
- }
815
-
816
- .stApp {
817
- background: url('https://www.transparenttextures.com/patterns/cartographer.png');
818
- }
819
-
820
- .game-card {
821
- background-color: white;
822
- border-radius: 20px;
823
- padding: 25px;
824
- box-shadow: 0 8px 32px rgba(26, 83, 92, 0.2);
825
- border: 4px solid var(--game-purple);
826
- margin-bottom: 25px;
827
- transition: all 0.3s;
828
- }
829
-
830
- .game-card:hover {
831
- transform: translateY(-5px);
832
- box-shadow: 0 12px 24px rgba(26, 83, 92, 0.3);
833
- }
834
-
835
- .header {
836
- color: var(--dark);
837
- font-family: 'Fredoka One', cursive;
838
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
839
- }
840
-
841
- .concept-card {
842
- background: linear-gradient(145deg, #ffffff, #f0f0f0);
843
- border-radius: 15px;
844
- padding: 15px;
845
- margin: 10px 0;
846
- border-left: 5px solid var(--secondary);
847
- box-shadow: 0 4px 12px rgba(0,0,0,0.1);
848
- }
849
-
850
- .stButton>button {
851
- background: linear-gradient(45deg, var(--game-purple), var(--game-blue));
852
- color: white;
853
- border-radius: 50px;
854
- padding: 12px 28px;
855
- font-weight: bold;
856
- font-size: 20px;
857
- border: none;
858
- transition: all 0.3s;
859
- font-family: 'Fredoka One', cursive;
860
- }
861
-
862
- .stButton>button:hover {
863
- transform: scale(1.05);
864
- box-shadow: 0 8px 16px rgba(0,0,0,0.2);
865
- }
866
-
867
- .stTextInput>div>div>input {
868
- border-radius: 20px;
869
- padding: 14px;
870
- border: 3px solid var(--accent);
871
- font-size: 18px;
872
- }
873
-
874
- .tabs {
875
- display: flex;
876
- gap: 10px;
877
- margin-bottom: 20px;
878
- overflow-x: auto;
879
- background: rgba(255,255,255,0.7);
880
- padding: 10px;
881
- border-radius: 20px;
882
- }
883
-
884
- .tab {
885
- padding: 12px 24px;
886
- background-color: var(--accent);
887
- border-radius: 15px;
888
- cursor: pointer;
889
- font-weight: bold;
890
- white-space: nowrap;
891
- font-family: 'Fredoka One', cursive;
892
- font-size: 18px;
893
- transition: all 0.3s;
894
- }
895
-
896
- .tab.active {
897
- background: linear-gradient(45deg, var(--game-purple), var(--game-blue));
898
- color: white;
899
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
900
- }
901
-
902
- .game-preview {
903
- border: 4px solid var(--game-blue);
904
- border-radius: 20px;
905
- overflow: hidden;
906
- background: linear-gradient(135deg, #a2d2ff, #bde0fe);
907
- padding: 20px;
908
- margin: 20px 0;
909
- }
910
-
911
- .character {
912
- font-size: 64px;
913
- text-align: center;
914
- margin: 20px 0;
915
- text-shadow: 4px 4px 8px rgba(0,0,0,0.2);
916
- }
917
-
918
- .game-container {
919
- background: rgba(255,255,255,0.9);
920
- border-radius: 20px;
921
- padding: 30px;
922
- box-shadow: 0 8px 32px rgba(0,0,0,0.1);
923
- margin: 20px 0;
924
- }
925
-
926
- .code-block {
927
- background: #2b2d42;
928
- color: #f8f9fa;
929
- border-radius: 15px;
930
- padding: 20px;
931
- font-family: 'Courier New', monospace;
932
- overflow-x: auto;
933
- margin: 20px 0;
934
- }
935
-
936
- .concept-emoji {
937
- font-size: 36px;
938
- margin-right: 15px;
939
- vertical-align: middle;
940
- }
941
-
942
- .game-title {
943
- font-family: 'Fredoka One', cursive;
944
- color: var(--game-purple);
945
- text-align: center;
946
- font-size: 32px;
947
- margin-bottom: 20px;
948
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
949
- }
950
-
951
- @media (max-width: 768px) {
952
- .tabs {
953
- flex-wrap: wrap;
954
- }
955
-
956
- .character {
957
- font-size: 48px;
958
- }
959
- }
960
- </style>
961
- """, unsafe_allow_html=True)
962
-
963
- # Initialize session state
964
- def init_session_state():
965
- if 'story' not in st.session_state:
966
- st.session_state.story = ""
967
- if 'concepts' not in st.session_state:
968
- st.session_state.concepts = []
969
- if 'game_scenario' not in st.session_state:
970
- st.session_state.game_scenario = ""
971
- if 'game_code' not in st.session_state:
972
- st.session_state.game_code = ""
973
- if 'game_explanation' not in st.session_state:
974
- st.session_state.game_explanation = ""
975
- if 'game_preview' not in st.session_state:
976
- st.session_state.game_preview = ""
977
- if 'active_tab' not in st.session_state:
978
- st.session_state.active_tab = "story"
979
- if 'loading' not in st.session_state:
980
- st.session_state.loading = False
981
-
982
- # Concept database
983
- CONCEPTS = {
984
- "loop": {
985
- "name": "Loop",
986
- "emoji": "🔄",
987
- "description": "Loops repeat actions multiple times",
988
- "example": "for i in range(5):\n print('Hello!')",
989
- "color": "#FF9E6D",
990
- "game_example": "Repeating a jump 5 times to cross a river"
991
- },
992
- "conditional": {
993
- "name": "Conditional",
994
- "emoji": "❓",
995
- "description": "Conditionals make decisions in code",
996
- "example": "if sunny:\n go_outside()\nelse:\n stay_inside()",
997
- "color": "#4ECDC4",
998
- "game_example": "Choosing different paths based on obstacles"
999
- },
1000
- "function": {
1001
- "name": "Function",
1002
- "emoji": "✨",
1003
- "description": "Functions are reusable blocks of code",
1004
- "example": "def greet(name):\n print(f'Hello {name}!')",
1005
- "color": "#FFD166",
1006
- "game_example": "Creating a jump function used multiple times"
1007
- },
1008
- "variable": {
1009
- "name": "Variable",
1010
- "emoji": "📦",
1011
- "description": "Variables store information",
1012
- "example": "score = 10\nplayer = 'Alex'",
1013
- "color": "#FF6B6B",
1014
- "game_example": "Keeping track of collected stars"
1015
- },
1016
- "list": {
1017
- "name": "List",
1018
- "emoji": "📝",
1019
- "description": "Lists store collections of items",
1020
- "example": "fruits = ['apple', 'banana', 'orange']",
1021
- "color": "#1A535C",
1022
- "game_example": "Storing collected treasures in a backpack"
1023
- }
1024
- }
1025
-
1026
- # Initialize Groq client
1027
- def get_groq_client():
1028
- try:
1029
- # Use a free proxy for Groq API access
1030
- return Groq(api_key="free-proxy-key", base_url="https://api.groq.com/openai/v1")
1031
- except:
1032
- st.error("Could not initialize Groq client. Using fallback method.")
1033
- return None
1034
-
1035
- # Analyze story and extract concepts
1036
- def analyze_story(story):
1037
- """Analyze story and identify programming concepts"""
1038
- story_lower = story.lower()
1039
- detected_concepts = []
1040
-
1041
- # Check for loops
1042
- if any(word in story_lower for word in ["times", "repeat", "again", "multiple"]):
1043
- detected_concepts.append("loop")
1044
-
1045
- # Check for conditionals
1046
- if any(word in story_lower for word in ["if", "when", "unless", "whether", "decide"]):
1047
- detected_concepts.append("conditional")
1048
-
1049
- # Check for functions
1050
- if any(word in story_lower for word in ["make", "create", "do", "perform", "cast"]):
1051
- detected_concepts.append("function")
1052
-
1053
- # Check for variables
1054
- if any(word in story_lower for word in ["is", "has", "set to", "value", "score"]):
1055
- detected_concepts.append("variable")
1056
-
1057
- # Check for lists
1058
- if any(word in story_lower for word in ["and", "many", "several", "collection", "items"]):
1059
- detected_concepts.append("list")
1060
-
1061
- return list(set(detected_concepts))
1062
-
1063
- # Generate game scenario using Groq
1064
- def generate_game_scenario(story, concepts):
1065
- """Generate a game scenario based on the story and concepts"""
1066
- try:
1067
- # Use Groq API for fast response
1068
- client = get_groq_client()
1069
- if client:
1070
- system_prompt = (
1071
- "You are an expert in creating educational games for children. "
1072
- "Create a simple 3D game scenario based on the child's story. "
1073
- "The game should teach programming concepts through gameplay. "
1074
- "Structure your response with:\n"
1075
- "Game Title: ...\n"
1076
- "Game Objective: ...\n"
1077
- "Characters: ...\n"
1078
- "Game Mechanics: ...\n"
1079
- "Coding Concepts: Explain how these programming concepts are used: " + ", ".join(concepts) + "\n"
1080
- "Visual Description: Describe the game world visually\n"
1081
- "Keep it under 200 words and suitable for children aged 6-12."
1082
- )
1083
-
1084
- response = client.chat.completions.create(
1085
- model="llama3-70b-8192",
1086
- messages=[
1087
- {"role": "system", "content": system_prompt},
1088
- {"role": "user", "content": story}
1089
- ],
1090
- temperature=0.7,
1091
- max_tokens=500
1092
- )
1093
- return response.choices[0].message.content
1094
- except Exception as e:
1095
- st.error(f"Groq API error: {str(e)}")
1096
-
1097
- # Fallback to Hugging Face model
1098
- try:
1099
- generator = pipeline("text-generation", model="HuggingFaceH4/zephyr-7b-beta")
1100
- prompt = (
1101
- f"Create a children's educational game based on this story: {story}\n"
1102
- f"Game should teach these programming concepts: {', '.join(concepts)}\n"
1103
- "Structure response with:\n"
1104
- "Game Title: ...\n"
1105
- "Game Objective: ...\n"
1106
- "Characters: ...\n"
1107
- "Game Mechanics: ...\n"
1108
- "Coding Concepts: ...\n"
1109
- "Visual Description: ...\n"
1110
- )
1111
- result = generator(prompt, max_length=400, do_sample=True, temperature=0.7)
1112
- return result[0]['generated_text']
1113
- except:
1114
- # Final fallback
1115
- return (
1116
- f"Game Title: {story[:20]} Adventure\n"
1117
- f"Game Objective: Complete challenges based on the story: {story[:100]}...\n"
1118
- "Characters: Hero character based on the story\n"
1119
- "Game Mechanics: Navigate through levels, collect items, solve puzzles\n"
1120
- f"Coding Concepts: This game teaches {', '.join(concepts)} through gameplay\n"
1121
- "Visual Description: Colorful 3D world with characters and obstacles"
1122
- )
1123
-
1124
- # Generate game code explanation
1125
- def generate_game_explanation(story, concepts, game_scenario):
1126
- """Generate explanation of game code"""
1127
- try:
1128
- client = get_groq_client()
1129
- if client:
1130
- system_prompt = (
1131
- "Explain how the game code implements the programming concepts in a way "
1132
- "a child can understand. Use simple analogies and relate to the story. "
1133
- "Structure your response with:\n"
1134
- "Introduction: ...\n"
1135
- "Concept 1: ...\n"
1136
- "Concept 2: ...\n"
1137
- "Conclusion: ...\n"
1138
- "Keep it under 300 words and fun for kids."
1139
- )
1140
-
1141
- response = client.chat.completions.create(
1142
- model="llama3-70b-8192",
1143
- messages=[
1144
- {"role": "system", "content": system_prompt},
1145
- {"role": "user", "content": f"Story: {story}\nGame Scenario: {game_scenario}\nConcepts: {', '.join(concepts)}"}
1146
- ],
1147
- temperature=0.7,
1148
- max_tokens=600
1149
- )
1150
- return response.choices[0].message.content
1151
- except:
1152
- pass
1153
-
1154
- # Fallback
1155
- concept_explanations = "\n".join(
1156
- [f"- {CONCEPTS[c]['name']}: {CONCEPTS[c]['game_example']}" for c in concepts]
1157
- )
1158
- return (
1159
- f"In this game based on your story '{story[:20]}...', we use programming concepts to make it work:\n"
1160
- f"{concept_explanations}\n\n"
1161
- "The code brings your story to life in a 3D game world!"
1162
- )
1163
-
1164
- # Generate simple game code
1165
- def generate_game_code(story, concepts):
1166
- """Generate simple PyGame code for the game"""
1167
- # This is a template - in a real app, this would be dynamically generated
1168
- return f"""
1169
- # {story[:30]} Adventure Game
1170
- import pygame
1171
- import random
1172
-
1173
- # Initialize pygame
1174
- pygame.init()
1175
-
1176
- # Game setup
1177
- WIDTH, HEIGHT = 800, 600
1178
- screen = pygame.display.set_mode((WIDTH, HEIGHT))
1179
- pygame.display.set_caption("{story[:20]} Adventure")
1180
- clock = pygame.time.Clock()
1181
-
1182
- # Colors
1183
- BACKGROUND = (173, 216, 230) # Light blue
1184
- PLAYER_COLOR = (255, 0, 0) # Red
1185
- GOAL_COLOR = (0, 255, 0) # Green
1186
- OBSTACLE_COLOR = (139, 69, 19) # Brown
1187
-
1188
- # Player setup
1189
- player_size = 50
1190
- player_x = 100
1191
- player_y = HEIGHT // 2
1192
- player_speed = 5
1193
-
1194
- # Goal setup
1195
- goal_size = 40
1196
- goal_x = WIDTH - 150
1197
- goal_y = HEIGHT // 2
1198
-
1199
- # Variables concept: Tracking score
1200
- score = 0
1201
- font = pygame.font.SysFont(None, 36)
1202
-
1203
- # List concept: Creating obstacles
1204
- obstacles = []
1205
- for i in range(5):
1206
- obstacles.append([
1207
- random.randint(200, WIDTH - 100),
1208
- random.randint(50, HEIGHT - 100),
1209
- random.randint(20, 50),
1210
- random.randint(20, 50)
1211
- ])
1212
-
1213
- # Game loop
1214
- running = True
1215
- while running:
1216
- # Event handling
1217
- for event in pygame.event.get():
1218
- if event.type == pygame.QUIT:
1219
- running = False
1220
-
1221
- # Player movement
1222
- keys = pygame.key.get_pressed()
1223
- if keys[pygame.K_UP]:
1224
- player_y -= player_speed
1225
- if keys[pygame.K_DOWN]:
1226
- player_y += player_speed
1227
- if keys[pygame.K_LEFT]:
1228
- player_x -= player_speed
1229
- if keys[pygame.K_RIGHT]:
1230
- player_x += player_speed
1231
-
1232
- # Boundary checking
1233
- player_x = max(0, min(WIDTH - player_size, player_x))
1234
- player_y = max(0, min(HEIGHT - player_size, player_y))
1235
-
1236
- # Collision detection with goal
1237
- player_rect = pygame.Rect(player_x, player_y, player_size, player_size)
1238
- goal_rect = pygame.Rect(goal_x, goal_y, goal_size, goal_size)
1239
-
1240
- # Conditional concept: Check for collision
1241
- if player_rect.colliderect(goal_rect):
1242
- # Function concept: Increase score
1243
- score += 1
1244
- # Move goal to new position
1245
- goal_x = random.randint(100, WIDTH - 100)
1246
- goal_y = random.randint(50, HEIGHT - 100)
1247
-
1248
- # Drawing
1249
- screen.fill(BACKGROUND)
1250
-
1251
- # Draw obstacles
1252
- for obstacle in obstacles:
1253
- pygame.draw.rect(screen, OBSTACLE_COLOR,
1254
- (obstacle[0], obstacle[1], obstacle[2], obstacle[3]))
1255
-
1256
- # Draw player and goal
1257
- pygame.draw.rect(screen, PLAYER_COLOR,
1258
- (player_x, player_y, player_size, player_size))
1259
- pygame.draw.rect(screen, GOAL_COLOR,
1260
- (goal_x, goal_y, goal_size, goal_size))
1261
-
1262
- # Display score
1263
- score_text = font.render(f"Stars: {{score}}", True, (0, 0, 0))
1264
- screen.blit(score_text, (20, 20))
1265
-
1266
- # Update display
1267
- pygame.display.flip()
1268
- clock.tick(60)
1269
-
1270
- pygame.quit()
1271
- """
1272
-
1273
- # Generate game preview visualization
1274
- def generate_game_preview(game_scenario):
1275
- """Generate a visual preview of the game"""
1276
- try:
1277
- # Extract title from game scenario
1278
- title_match = re.search(r"Game Title: (.+)", game_scenario)
1279
- title = title_match.group(1) if title_match else "Your Adventure"
1280
-
1281
- # Create a simple visualization
1282
- fig, ax = plt.subplots(figsize=(10, 6))
1283
- ax.set_facecolor('#a2d2ff')
1284
- ax.set_xlim(0, 10)
1285
- ax.set_ylim(0, 6)
1286
-
1287
- # Draw game elements
1288
- ax.text(5, 5, title, fontsize=20, ha='center', color='#9b5de5')
1289
- ax.plot([1, 9], [3, 3], 'k-', linewidth=2) # Ground
1290
-
1291
- # Player character
1292
- ax.plot(2, 3.5, 'ro', markersize=15)
1293
-
1294
- # Goal
1295
- ax.plot(8, 3.5, 'go', markersize=15)
1296
-
1297
- # Obstacles
1298
- for i in range(3):
1299
- x = random.uniform(3, 7)
1300
- y = random.uniform(3.2, 4)
1301
- ax.plot(x, y, 's', color='#8d99ae', markersize=12)
1302
-
1303
- # Path
1304
- ax.plot([2, 8], [3.5, 3.5], 'y--', linewidth=2)
1305
-
1306
- ax.axis('off')
1307
- ax.set_title("Game Preview", fontsize=16)
1308
-
1309
- # Save to bytes
1310
- buf = io.BytesIO()
1311
- plt.savefig(buf, format='png', dpi=100, bbox_inches='tight')
1312
- buf.seek(0)
1313
- return buf
1314
- except:
1315
- return None
1316
-
1317
- # Main application function
1318
- def main():
1319
- init_session_state()
1320
-
1321
- st.title("🎮 StoryCoder - Learn Coding Through Games!")
1322
- st.subheader("Turn your story into a 3D game and discover coding secrets!")
1323
-
1324
- # Create tabs
1325
- st.markdown('<div class="tabs">', unsafe_allow_html=True)
1326
- col1, col2, col3, col4, col5 = st.columns(5)
1327
- with col1:
1328
- if st.button("📖 Create Story", use_container_width=True):
1329
- st.session_state.active_tab = "story"
1330
- with col2:
1331
- if st.button("🎮 Play Game", use_container_width=True):
1332
- st.session_state.active_tab = "game"
1333
- with col3:
1334
- if st.button("🔍 Concepts", use_container_width=True):
1335
- st.session_state.active_tab = "concepts"
1336
- with col4:
1337
- if st.button("💻 Game Code", use_container_width=True):
1338
- st.session_state.active_tab = "code"
1339
- with col5:
1340
- if st.button("🔄 New Story", use_container_width=True):
1341
- st.session_state.story = ""
1342
- st.session_state.concepts = []
1343
- st.session_state.game_scenario = ""
1344
- st.session_state.game_code = ""
1345
- st.session_state.game_explanation = ""
1346
- st.session_state.game_preview = ""
1347
- st.session_state.active_tab = "story"
1348
- st.markdown('</div>', unsafe_allow_html=True)
1349
-
1350
- # Story creation tab
1351
- if st.session_state.active_tab == "story":
1352
- with st.container():
1353
- st.header("📖 Create Your Story")
1354
- st.write("Write a short story (2-5 sentences) and I'll turn it into a 3D game!")
1355
-
1356
- story = st.text_area(
1357
- "Your story:",
1358
- height=200,
1359
- placeholder="Once upon a time, a brave knight had to collect 5 magical stars in a castle...",
1360
- value=st.session_state.story,
1361
- key="story_input"
1362
- )
1363
-
1364
- if st.button("Create Game!", use_container_width=True):
1365
- if len(story) < 10:
1366
- st.error("Your story needs to be at least 10 characters long!")
1367
- else:
1368
- st.session_state.story = story
1369
- st.session_state.loading = True
1370
-
1371
- with st.spinner("🧠 Analyzing your story for coding concepts..."):
1372
- st.session_state.concepts = analyze_story(story)
1373
-
1374
- with st.spinner("🎮 Creating your 3D game scenario..."):
1375
- st.session_state.game_scenario = generate_game_scenario(
1376
- story, st.session_state.concepts
1377
- )
1378
-
1379
- with st.spinner("💻 Generating game code..."):
1380
- st.session_state.game_code = generate_game_code(
1381
- story, st.session_state.concepts
1382
- )
1383
-
1384
- with st.spinner("📚 Creating coding explanations..."):
1385
- st.session_state.game_explanation = generate_game_explanation(
1386
- story, st.session_state.concepts, st.session_state.game_scenario
1387
- )
1388
-
1389
- with st.spinner("🖼️ Generating game preview..."):
1390
- preview = generate_game_preview(st.session_state.game_scenario)
1391
- if preview:
1392
- st.session_state.game_preview = preview
1393
-
1394
- st.session_state.active_tab = "game"
1395
- st.session_state.loading = False
1396
- st.rerun()
1397
-
1398
- # Show examples
1399
- st.subheader("✨ Story Examples")
1400
- col1, col2, col3 = st.columns(3)
1401
- with col1:
1402
- st.caption("Space Explorer")
1403
- st.code('"An astronaut needs to collect 3 stars while avoiding asteroids"', language="text")
1404
- st.image("https://i.imgur.com/7zQY1eE.gif",
1405
- use_column_width=True,
1406
- caption="Space Explorer Game")
1407
- with col2:
1408
- st.caption("Jungle Adventure")
1409
- st.code('"A monkey swings through trees to collect bananas before sunset"', language="text")
1410
- st.image("https://i.imgur.com/5X8jYAy.gif",
1411
- use_column_width=True,
1412
- caption="Jungle Adventure Game")
1413
- with col3:
1414
- st.caption("Dragon Quest")
1415
- st.code('"A dragon flies through clouds to collect magic crystals"', language="text")
1416
- st.image("https://i.imgur.com/9zJkQ7P.gif",
1417
- use_column_width=True,
1418
- caption="Dragon Quest Game")
1419
-
1420
- # Game tab
1421
- elif st.session_state.active_tab == "game":
1422
- st.header("🎮 Your Story Game")
1423
-
1424
- if not st.session_state.story:
1425
- st.warning("Please create a story first!")
1426
- st.session_state.active_tab = "story"
1427
- st.rerun()
1428
-
1429
- # Display game scenario
1430
- st.subheader("🌟 Game Scenario")
1431
- st.markdown(f'<div class="game-card">{st.session_state.game_scenario}</div>', unsafe_allow_html=True)
1432
-
1433
- # Display game preview
1434
- st.subheader("🖼️ Game Preview")
1435
- if st.session_state.game_preview:
1436
- st.image(st.session_state.game_preview, use_container_width=True)
1437
- else:
1438
- st.warning("Game preview couldn't be generated. Showing example instead.")
1439
- st.image("https://i.imgur.com/7zQY1eE.gif", use_container_width=True)
1440
-
1441
- # Game explanation
1442
- st.subheader("📚 How This Game Teaches Coding")
1443
- st.markdown(f'<div class="game-card">{st.session_state.game_explanation}</div>', unsafe_allow_html=True)
1444
-
1445
- # Play instructions
1446
- st.subheader("▶️ How to Play")
1447
- st.markdown("""
1448
- <div class="game-card">
1449
- <ol>
1450
- <li>Download the game code from the <b>Game Code</b> tab</li>
1451
- <li>Install Python from <a href="https://python.org">python.org</a></li>
1452
- <li>Install PyGame: <code>pip install pygame</code></li>
1453
- <li>Run the game: <code>python your_game.py</code></li>
1454
- <li>Use arrow keys to move your character!</li>
1455
- </ol>
1456
- </div>
1457
- """, unsafe_allow_html=True)
1458
-
1459
- if st.button("Learn Coding Concepts", use_container_width=True):
1460
- st.session_state.active_tab = "concepts"
1461
- st.rerun()
1462
-
1463
- # Concepts tab
1464
- elif st.session_state.active_tab == "concepts":
1465
- st.header("🔍 Coding Concepts in Your Game")
1466
- st.subheader("Your game teaches these programming concepts:")
1467
-
1468
- if not st.session_state.concepts:
1469
- st.warning("No concepts detected in your story! Try adding words like '3 times', 'if', or 'collect'.")
1470
- else:
1471
- for concept in st.session_state.concepts:
1472
- if concept in CONCEPTS:
1473
- details = CONCEPTS[concept]
1474
- st.markdown(f"""
1475
- <div class="concept-card" style="border-left: 5px solid {details['color']};">
1476
- <div style="display:flex; align-items:center; gap:15px;">
1477
- <span style="font-size:36px;">{details['emoji']}</span>
1478
- <h3 style="color:{details['color']};">{details['name']}</h3>
1479
- </div>
1480
- <p>{details['description']}</p>
1481
- <p><b>In your game:</b> {details['game_example']}</p>
1482
- <pre style="background:#f0f0f0; padding:10px; border-radius:8px;">{details['example']}</pre>
1483
- </div>
1484
- """, unsafe_allow_html=True)
1485
-
1486
- if st.button("See the Game Code", use_container_width=True):
1487
- st.session_state.active_tab = "code"
1488
- st.rerun()
1489
-
1490
- # Code tab
1491
- elif st.session_state.active_tab == "code":
1492
- st.header("💻 Game Code")
1493
- st.write("Here's the Python code for your game. Download it and run on your computer!")
1494
-
1495
- if st.session_state.game_code:
1496
- # Display code with syntax highlighting
1497
- st.subheader("Your Game Code")
1498
- st.code(st.session_state.game_code, language="python")
1499
-
1500
- # Download button
1501
- st.download_button(
1502
- label="📥 Download Game Code",
1503
- data=st.session_state.game_code,
1504
- file_name="story_game.py",
1505
- mime="text/python",
1506
- use_container_width=True
1507
- )
1508
-
1509
- # Game running instructions
1510
- st.subheader("🖥️ How to Run Your Game")
1511
- st.markdown("""
1512
- <div class="game-card">
1513
- <ol>
1514
- <li>Install Python from <a href="https://python.org">python.org</a></li>
1515
- <li>Install PyGame: Open command prompt and type <code>pip install pygame</code></li>
1516
- <li>Save the game code to a file named <code>my_game.py</code></li>
1517
- <li>Run the game: <code>python my_game.py</code></li>
1518
- <li>Use arrow keys to play!</li>
1519
- </ol>
1520
- </div>
1521
- """, unsafe_allow_html=True)
1522
-
1523
- # What to expect
1524
- st.subheader("🎮 What to Expect When Playing")
1525
- st.markdown("""
1526
- <div class="game-card">
1527
- <ul>
1528
- <li>Move your character (red square) with arrow keys</li>
1529
- <li>Collect the green stars to increase your score</li>
1530
- <li>Avoid the brown obstacles</li>
1531
- <li>See how programming concepts make the game work!</li>
1532
- </ul>
1533
- </div>
1534
- """, unsafe_allow_html=True)
1535
- else:
1536
- st.warning("No game code generated yet!")
1537
-
1538
- if st.button("Create Another Story!", use_container_width=True):
1539
- st.session_state.active_tab = "story"
1540
- st.rerun()
1541
-
1542
- if __name__ == "__main__":
1543
- main()# app.py - Game-Based Learning Version
1544
- import streamlit as st
1545
- import os
1546
- import time
1547
- import random
1548
- import json
1549
- import base64
1550
- import requests
1551
- import re
1552
- from PIL import Image
1553
- import io
1554
- import matplotlib.pyplot as plt
1555
- from groq import Groq
1556
- from transformers import pipeline
1557
- import torch
1558
-
1559
- # Configure Streamlit page
1560
- st.set_page_config(
1561
- page_title="StoryCoder - Learn Coding Through Games",
1562
- page_icon="🎮",
1563
- layout="wide",
1564
- initial_sidebar_state="expanded"
1565
- )
1566
-
1567
- # Custom CSS for game-themed UI
1568
- st.markdown("""
1569
- <style>
1570
- @import url('https://fonts.googleapis.com/css2?family=Fredoka+One&family=Comic+Neue:wght@700&display=swap');
1571
-
1572
- :root {
1573
- --primary: #FF6B6B;
1574
- --secondary: #4ECDC4;
1575
- --accent: #FFD166;
1576
- --dark: #1A535C;
1577
- --light: #F7FFF7;
1578
- --game-blue: #118AB2;
1579
- --game-purple: #9B5DE5;
1580
- }
1581
-
1582
- body {
1583
- background: linear-gradient(135deg, #E8F4F8 0%, #FFDEE9 100%);
1584
- font-family: 'Comic Neue', cursive;
1585
- }
1586
-
1587
- .stApp {
1588
- background: url('https://www.transparenttextures.com/patterns/cartographer.png');
1589
- }
1590
-
1591
- .game-card {
1592
- background-color: white;
1593
- border-radius: 20px;
1594
- padding: 25px;
1595
- box-shadow: 0 8px 32px rgba(26, 83, 92, 0.2);
1596
- border: 4px solid var(--game-purple);
1597
- margin-bottom: 25px;
1598
- transition: all 0.3s;
1599
- }
1600
-
1601
- .game-card:hover {
1602
- transform: translateY(-5px);
1603
- box-shadow: 0 12px 24px rgba(26, 83, 92, 0.3);
1604
- }
1605
-
1606
- .header {
1607
- color: var(--dark);
1608
- font-family: 'Fredoka One', cursive;
1609
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
1610
- }
1611
-
1612
- .concept-card {
1613
- background: linear-gradient(145deg, #ffffff, #f0f0f0);
1614
- border-radius: 15px;
1615
- padding: 15px;
1616
- margin: 10px 0;
1617
- border-left: 5px solid var(--secondary);
1618
- box-shadow: 0 4px 12px rgba(0,0,0,0.1);
1619
- }
1620
-
1621
- .stButton>button {
1622
- background: linear-gradient(45deg, var(--game-purple), var(--game-blue));
1623
- color: white;
1624
- border-radius: 50px;
1625
- padding: 12px 28px;
1626
- font-weight: bold;
1627
- font-size: 20px;
1628
- border: none;
1629
- transition: all 0.3s;
1630
- font-family: 'Fredoka One', cursive;
1631
- }
1632
-
1633
- .stButton>button:hover {
1634
- transform: scale(1.05);
1635
- box-shadow: 0 8px 16px rgba(0,0,0,0.2);
1636
- }
1637
-
1638
- .stTextInput>div>div>input {
1639
- border-radius: 20px;
1640
- padding: 14px;
1641
- border: 3px solid var(--accent);
1642
- font-size: 18px;
1643
- }
1644
-
1645
- .tabs {
1646
- display: flex;
1647
- gap: 10px;
1648
- margin-bottom: 20px;
1649
- overflow-x: auto;
1650
- background: rgba(255,255,255,0.7);
1651
- padding: 10px;
1652
- border-radius: 20px;
1653
- }
1654
-
1655
- .tab {
1656
- padding: 12px 24px;
1657
- background-color: var(--accent);
1658
- border-radius: 15px;
1659
- cursor: pointer;
1660
- font-weight: bold;
1661
- white-space: nowrap;
1662
- font-family: 'Fredoka One', cursive;
1663
- font-size: 18px;
1664
- transition: all 0.3s;
1665
- }
1666
-
1667
- .tab.active {
1668
- background: linear-gradient(45deg, var(--game-purple), var(--game-blue));
1669
- color: white;
1670
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
1671
- }
1672
-
1673
- .game-preview {
1674
- border: 4px solid var(--game-blue);
1675
- border-radius: 20px;
1676
- overflow: hidden;
1677
- background: linear-gradient(135deg, #a2d2ff, #bde0fe);
1678
- padding: 20px;
1679
- margin: 20px 0;
1680
- }
1681
-
1682
- .character {
1683
- font-size: 64px;
1684
- text-align: center;
1685
- margin: 20px 0;
1686
- text-shadow: 4px 4px 8px rgba(0,0,0,0.2);
1687
- }
1688
-
1689
- .game-container {
1690
- background: rgba(255,255,255,0.9);
1691
- border-radius: 20px;
1692
- padding: 30px;
1693
- box-shadow: 0 8px 32px rgba(0,0,0,0.1);
1694
- margin: 20px 0;
1695
- }
1696
-
1697
- .code-block {
1698
- background: #2b2d42;
1699
- color: #f8f9fa;
1700
- border-radius: 15px;
1701
- padding: 20px;
1702
- font-family: 'Courier New', monospace;
1703
- overflow-x: auto;
1704
- margin: 20px 0;
1705
- }
1706
-
1707
- .concept-emoji {
1708
- font-size: 36px;
1709
- margin-right: 15px;
1710
- vertical-align: middle;
1711
- }
1712
-
1713
- .game-title {
1714
- font-family: 'Fredoka One', cursive;
1715
- color: var(--game-purple);
1716
- text-align: center;
1717
- font-size: 32px;
1718
- margin-bottom: 20px;
1719
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
1720
- }
1721
-
1722
- @media (max-width: 768px) {
1723
- .tabs {
1724
- flex-wrap: wrap;
1725
- }
1726
-
1727
- .character {
1728
- font-size: 48px;
1729
- }
1730
- }
1731
- </style>
1732
- """, unsafe_allow_html=True)
1733
-
1734
- # Initialize session state
1735
- def init_session_state():
1736
- if 'story' not in st.session_state:
1737
- st.session_state.story = ""
1738
- if 'concepts' not in st.session_state:
1739
- st.session_state.concepts = []
1740
- if 'game_scenario' not in st.session_state:
1741
- st.session_state.game_scenario = ""
1742
- if 'game_code' not in st.session_state:
1743
- st.session_state.game_code = ""
1744
- if 'game_explanation' not in st.session_state:
1745
- st.session_state.game_explanation = ""
1746
- if 'game_preview' not in st.session_state:
1747
- st.session_state.game_preview = ""
1748
- if 'active_tab' not in st.session_state:
1749
- st.session_state.active_tab = "story"
1750
- if 'loading' not in st.session_state:
1751
- st.session_state.loading = False
1752
-
1753
- # Concept database
1754
- CONCEPTS = {
1755
- "loop": {
1756
- "name": "Loop",
1757
- "emoji": "🔄",
1758
- "description": "Loops repeat actions multiple times",
1759
- "example": "for i in range(5):\n print('Hello!')",
1760
- "color": "#FF9E6D",
1761
- "game_example": "Repeating a jump 5 times to cross a river"
1762
- },
1763
- "conditional": {
1764
- "name": "Conditional",
1765
- "emoji": "❓",
1766
- "description": "Conditionals make decisions in code",
1767
- "example": "if sunny:\n go_outside()\nelse:\n stay_inside()",
1768
- "color": "#4ECDC4",
1769
- "game_example": "Choosing different paths based on obstacles"
1770
- },
1771
- "function": {
1772
- "name": "Function",
1773
- "emoji": "✨",
1774
- "description": "Functions are reusable blocks of code",
1775
- "example": "def greet(name):\n print(f'Hello {name}!')",
1776
- "color": "#FFD166",
1777
- "game_example": "Creating a jump function used multiple times"
1778
- },
1779
- "variable": {
1780
- "name": "Variable",
1781
- "emoji": "📦",
1782
- "description": "Variables store information",
1783
- "example": "score = 10\nplayer = 'Alex'",
1784
- "color": "#FF6B6B",
1785
- "game_example": "Keeping track of collected stars"
1786
- },
1787
- "list": {
1788
- "name": "List",
1789
- "emoji": "📝",
1790
- "description": "Lists store collections of items",
1791
- "example": "fruits = ['apple', 'banana', 'orange']",
1792
- "color": "#1A535C",
1793
- "game_example": "Storing collected treasures in a backpack"
1794
- }
1795
- }
1796
-
1797
- # Initialize Groq client
1798
- def get_groq_client():
1799
- try:
1800
- # Use a free proxy for Groq API access
1801
- return Groq(api_key="free-proxy-key", base_url="https://api.groq.com/openai/v1")
1802
- except:
1803
- st.error("Could not initialize Groq client. Using fallback method.")
1804
- return None
1805
-
1806
- # Analyze story and extract concepts
1807
- def analyze_story(story):
1808
- """Analyze story and identify programming concepts"""
1809
- story_lower = story.lower()
1810
- detected_concepts = []
1811
-
1812
- # Check for loops
1813
- if any(word in story_lower for word in ["times", "repeat", "again", "multiple"]):
1814
- detected_concepts.append("loop")
1815
-
1816
- # Check for conditionals
1817
- if any(word in story_lower for word in ["if", "when", "unless", "whether", "decide"]):
1818
- detected_concepts.append("conditional")
1819
-
1820
- # Check for functions
1821
- if any(word in story_lower for word in ["make", "create", "do", "perform", "cast"]):
1822
- detected_concepts.append("function")
1823
-
1824
- # Check for variables
1825
- if any(word in story_lower for word in ["is", "has", "set to", "value", "score"]):
1826
- detected_concepts.append("variable")
1827
-
1828
- # Check for lists
1829
- if any(word in story_lower for word in ["and", "many", "several", "collection", "items"]):
1830
- detected_concepts.append("list")
1831
-
1832
- return list(set(detected_concepts))
1833
-
1834
- # Generate game scenario using Groq
1835
- def generate_game_scenario(story, concepts):
1836
- """Generate a game scenario based on the story and concepts"""
1837
- try:
1838
- # Use Groq API for fast response
1839
- client = get_groq_client()
1840
- if client:
1841
- system_prompt = (
1842
- "You are an expert in creating educational games for children. "
1843
- "Create a simple 3D game scenario based on the child's story. "
1844
- "The game should teach programming concepts through gameplay. "
1845
- "Structure your response with:\n"
1846
- "Game Title: ...\n"
1847
- "Game Objective: ...\n"
1848
- "Characters: ...\n"
1849
- "Game Mechanics: ...\n"
1850
- "Coding Concepts: Explain how these programming concepts are used: " + ", ".join(concepts) + "\n"
1851
- "Visual Description: Describe the game world visually\n"
1852
- "Keep it under 200 words and suitable for children aged 6-12."
1853
- )
1854
-
1855
- response = client.chat.completions.create(
1856
- model="llama3-70b-8192",
1857
- messages=[
1858
- {"role": "system", "content": system_prompt},
1859
- {"role": "user", "content": story}
1860
- ],
1861
- temperature=0.7,
1862
- max_tokens=500
1863
- )
1864
- return response.choices[0].message.content
1865
- except Exception as e:
1866
- st.error(f"Groq API error: {str(e)}")
1867
-
1868
- # Fallback to Hugging Face model
1869
- try:
1870
- generator = pipeline("text-generation", model="HuggingFaceH4/zephyr-7b-beta")
1871
- prompt = (
1872
- f"Create a children's educational game based on this story: {story}\n"
1873
- f"Game should teach these programming concepts: {', '.join(concepts)}\n"
1874
- "Structure response with:\n"
1875
- "Game Title: ...\n"
1876
- "Game Objective: ...\n"
1877
- "Characters: ...\n"
1878
- "Game Mechanics: ...\n"
1879
- "Coding Concepts: ...\n"
1880
- "Visual Description: ...\n"
1881
- )
1882
- result = generator(prompt, max_length=400, do_sample=True, temperature=0.7)
1883
- return result[0]['generated_text']
1884
- except:
1885
- # Final fallback
1886
- return (
1887
- f"Game Title: {story[:20]} Adventure\n"
1888
- f"Game Objective: Complete challenges based on the story: {story[:100]}...\n"
1889
- "Characters: Hero character based on the story\n"
1890
- "Game Mechanics: Navigate through levels, collect items, solve puzzles\n"
1891
- f"Coding Concepts: This game teaches {', '.join(concepts)} through gameplay\n"
1892
- "Visual Description: Colorful 3D world with characters and obstacles"
1893
- )
1894
-
1895
- # Generate game code explanation
1896
- def generate_game_explanation(story, concepts, game_scenario):
1897
- """Generate explanation of game code"""
1898
- try:
1899
- client = get_groq_client()
1900
- if client:
1901
- system_prompt = (
1902
- "Explain how the game code implements the programming concepts in a way "
1903
- "a child can understand. Use simple analogies and relate to the story. "
1904
- "Structure your response with:\n"
1905
- "Introduction: ...\n"
1906
- "Concept 1: ...\n"
1907
- "Concept 2: ...\n"
1908
- "Conclusion: ...\n"
1909
- "Keep it under 300 words and fun for kids."
1910
- )
1911
-
1912
- response = client.chat.completions.create(
1913
- model="llama3-70b-8192",
1914
- messages=[
1915
- {"role": "system", "content": system_prompt},
1916
- {"role": "user", "content": f"Story: {story}\nGame Scenario: {game_scenario}\nConcepts: {', '.join(concepts)}"}
1917
- ],
1918
- temperature=0.7,
1919
- max_tokens=600
1920
- )
1921
- return response.choices[0].message.content
1922
- except:
1923
- pass
1924
-
1925
- # Fallback
1926
- concept_explanations = "\n".join(
1927
- [f"- {CONCEPTS[c]['name']}: {CONCEPTS[c]['game_example']}" for c in concepts]
1928
- )
1929
- return (
1930
- f"In this game based on your story '{story[:20]}...', we use programming concepts to make it work:\n"
1931
- f"{concept_explanations}\n\n"
1932
- "The code brings your story to life in a 3D game world!"
1933
- )
1934
-
1935
- # Generate simple game code
1936
- def generate_game_code(story, concepts):
1937
- """Generate simple PyGame code for the game"""
1938
- # This is a template - in a real app, this would be dynamically generated
1939
- return f"""
1940
- # {story[:30]} Adventure Game
1941
- import pygame
1942
- import random
1943
-
1944
- # Initialize pygame
1945
- pygame.init()
1946
-
1947
- # Game setup
1948
- WIDTH, HEIGHT = 800, 600
1949
- screen = pygame.display.set_mode((WIDTH, HEIGHT))
1950
- pygame.display.set_caption("{story[:20]} Adventure")
1951
- clock = pygame.time.Clock()
1952
-
1953
- # Colors
1954
- BACKGROUND = (173, 216, 230) # Light blue
1955
- PLAYER_COLOR = (255, 0, 0) # Red
1956
- GOAL_COLOR = (0, 255, 0) # Green
1957
- OBSTACLE_COLOR = (139, 69, 19) # Brown
1958
-
1959
- # Player setup
1960
- player_size = 50
1961
- player_x = 100
1962
- player_y = HEIGHT // 2
1963
- player_speed = 5
1964
-
1965
- # Goal setup
1966
- goal_size = 40
1967
- goal_x = WIDTH - 150
1968
- goal_y = HEIGHT // 2
1969
-
1970
- # Variables concept: Tracking score
1971
- score = 0
1972
- font = pygame.font.SysFont(None, 36)
1973
-
1974
- # List concept: Creating obstacles
1975
- obstacles = []
1976
- for i in range(5):
1977
- obstacles.append([
1978
- random.randint(200, WIDTH - 100),
1979
- random.randint(50, HEIGHT - 100),
1980
- random.randint(20, 50),
1981
- random.randint(20, 50)
1982
- ])
1983
-
1984
- # Game loop
1985
- running = True
1986
- while running:
1987
- # Event handling
1988
- for event in pygame.event.get():
1989
- if event.type == pygame.QUIT:
1990
- running = False
1991
-
1992
- # Player movement
1993
- keys = pygame.key.get_pressed()
1994
- if keys[pygame.K_UP]:
1995
- player_y -= player_speed
1996
- if keys[pygame.K_DOWN]:
1997
- player_y += player_speed
1998
- if keys[pygame.K_LEFT]:
1999
- player_x -= player_speed
2000
- if keys[pygame.K_RIGHT]:
2001
- player_x += player_speed
2002
-
2003
- # Boundary checking
2004
- player_x = max(0, min(WIDTH - player_size, player_x))
2005
- player_y = max(0, min(HEIGHT - player_size, player_y))
2006
-
2007
- # Collision detection with goal
2008
- player_rect = pygame.Rect(player_x, player_y, player_size, player_size)
2009
- goal_rect = pygame.Rect(goal_x, goal_y, goal_size, goal_size)
2010
-
2011
- # Conditional concept: Check for collision
2012
- if player_rect.colliderect(goal_rect):
2013
- # Function concept: Increase score
2014
- score += 1
2015
- # Move goal to new position
2016
- goal_x = random.randint(100, WIDTH - 100)
2017
- goal_y = random.randint(50, HEIGHT - 100)
2018
-
2019
- # Drawing
2020
- screen.fill(BACKGROUND)
2021
-
2022
- # Draw obstacles
2023
- for obstacle in obstacles:
2024
- pygame.draw.rect(screen, OBSTACLE_COLOR,
2025
- (obstacle[0], obstacle[1], obstacle[2], obstacle[3]))
2026
-
2027
- # Draw player and goal
2028
- pygame.draw.rect(screen, PLAYER_COLOR,
2029
- (player_x, player_y, player_size, player_size))
2030
- pygame.draw.rect(screen, GOAL_COLOR,
2031
- (goal_x, goal_y, goal_size, goal_size))
2032
-
2033
- # Display score
2034
- score_text = font.render(f"Stars: {{score}}", True, (0, 0, 0))
2035
- screen.blit(score_text, (20, 20))
2036
-
2037
- # Update display
2038
- pygame.display.flip()
2039
- clock.tick(60)
2040
-
2041
- pygame.quit()
2042
- """
2043
-
2044
- # Generate game preview visualization
2045
- def generate_game_preview(game_scenario):
2046
- """Generate a visual preview of the game"""
2047
- try:
2048
- # Extract title from game scenario
2049
- title_match = re.search(r"Game Title: (.+)", game_scenario)
2050
- title = title_match.group(1) if title_match else "Your Adventure"
2051
-
2052
- # Create a simple visualization
2053
- fig, ax = plt.subplots(figsize=(10, 6))
2054
- ax.set_facecolor('#a2d2ff')
2055
- ax.set_xlim(0, 10)
2056
- ax.set_ylim(0, 6)
2057
-
2058
- # Draw game elements
2059
- ax.text(5, 5, title, fontsize=20, ha='center', color='#9b5de5')
2060
- ax.plot([1, 9], [3, 3], 'k-', linewidth=2) # Ground
2061
-
2062
- # Player character
2063
- ax.plot(2, 3.5, 'ro', markersize=15)
2064
-
2065
- # Goal
2066
- ax.plot(8, 3.5, 'go', markersize=15)
2067
-
2068
- # Obstacles
2069
- for i in range(3):
2070
- x = random.uniform(3, 7)
2071
- y = random.uniform(3.2, 4)
2072
- ax.plot(x, y, 's', color='#8d99ae', markersize=12)
2073
-
2074
- # Path
2075
- ax.plot([2, 8], [3.5, 3.5], 'y--', linewidth=2)
2076
-
2077
- ax.axis('off')
2078
- ax.set_title("Game Preview", fontsize=16)
2079
-
2080
- # Save to bytes
2081
- buf = io.BytesIO()
2082
- plt.savefig(buf, format='png', dpi=100, bbox_inches='tight')
2083
- buf.seek(0)
2084
- return buf
2085
- except:
2086
- return None
2087
-
2088
- # Main application function
2089
- def main():
2090
- init_session_state()
2091
-
2092
- st.title("🎮 StoryCoder - Learn Coding Through Games!")
2093
- st.subheader("Turn your story into a 3D game and discover coding secrets!")
2094
-
2095
- # Create tabs
2096
- st.markdown('<div class="tabs">', unsafe_allow_html=True)
2097
- col1, col2, col3, col4, col5 = st.columns(5)
2098
- with col1:
2099
- if st.button("📖 Create Story", use_container_width=True):
2100
- st.session_state.active_tab = "story"
2101
- with col2:
2102
- if st.button("🎮 Play Game", use_container_width=True):
2103
- st.session_state.active_tab = "game"
2104
- with col3:
2105
- if st.button("🔍 Concepts", use_container_width=True):
2106
- st.session_state.active_tab = "concepts"
2107
- with col4:
2108
- if st.button("💻 Game Code", use_container_width=True):
2109
- st.session_state.active_tab = "code"
2110
- with col5:
2111
- if st.button("🔄 New Story", use_container_width=True):
2112
- st.session_state.story = ""
2113
- st.session_state.concepts = []
2114
- st.session_state.game_scenario = ""
2115
- st.session_state.game_code = ""
2116
- st.session_state.game_explanation = ""
2117
- st.session_state.game_preview = ""
2118
- st.session_state.active_tab = "story"
2119
- st.markdown('</div>', unsafe_allow_html=True)
2120
-
2121
- # Story creation tab
2122
- if st.session_state.active_tab == "story":
2123
- with st.container():
2124
- st.header("���� Create Your Story")
2125
- st.write("Write a short story (2-5 sentences) and I'll turn it into a 3D game!")
2126
-
2127
- story = st.text_area(
2128
- "Your story:",
2129
- height=200,
2130
- placeholder="Once upon a time, a brave knight had to collect 5 magical stars in a castle...",
2131
- value=st.session_state.story,
2132
- key="story_input"
2133
- )
2134
-
2135
- if st.button("Create Game!", use_container_width=True):
2136
- if len(story) < 10:
2137
- st.error("Your story needs to be at least 10 characters long!")
2138
- else:
2139
- st.session_state.story = story
2140
- st.session_state.loading = True
2141
-
2142
- with st.spinner("🧠 Analyzing your story for coding concepts..."):
2143
- st.session_state.concepts = analyze_story(story)
2144
-
2145
- with st.spinner("🎮 Creating your 3D game scenario..."):
2146
- st.session_state.game_scenario = generate_game_scenario(
2147
- story, st.session_state.concepts
2148
- )
2149
-
2150
- with st.spinner("💻 Generating game code..."):
2151
- st.session_state.game_code = generate_game_code(
2152
- story, st.session_state.concepts
2153
- )
2154
-
2155
- with st.spinner("📚 Creating coding explanations..."):
2156
- st.session_state.game_explanation = generate_game_explanation(
2157
- story, st.session_state.concepts, st.session_state.game_scenario
2158
- )
2159
-
2160
- with st.spinner("🖼️ Generating game preview..."):
2161
- preview = generate_game_preview(st.session_state.game_scenario)
2162
- if preview:
2163
- st.session_state.game_preview = preview
2164
-
2165
- st.session_state.active_tab = "game"
2166
- st.session_state.loading = False
2167
- st.rerun()
2168
-
2169
- # Show examples
2170
- st.subheader("✨ Story Examples")
2171
- col1, col2, col3 = st.columns(3)
2172
- with col1:
2173
- st.caption("Space Explorer")
2174
- st.code('"An astronaut needs to collect 3 stars while avoiding asteroids"', language="text")
2175
- st.image("https://i.imgur.com/7zQY1eE.gif",
2176
- use_column_width=True,
2177
- caption="Space Explorer Game")
2178
- with col2:
2179
- st.caption("Jungle Adventure")
2180
- st.code('"A monkey swings through trees to collect bananas before sunset"', language="text")
2181
- st.image("https://i.imgur.com/5X8jYAy.gif",
2182
- use_column_width=True,
2183
- caption="Jungle Adventure Game")
2184
- with col3:
2185
- st.caption("Dragon Quest")
2186
- st.code('"A dragon flies through clouds to collect magic crystals"', language="text")
2187
- st.image("https://i.imgur.com/9zJkQ7P.gif",
2188
- use_column_width=True,
2189
- caption="Dragon Quest Game")
2190
-
2191
- # Game tab
2192
- elif st.session_state.active_tab == "game":
2193
- st.header("🎮 Your Story Game")
2194
-
2195
- if not st.session_state.story:
2196
- st.warning("Please create a story first!")
2197
- st.session_state.active_tab = "story"
2198
- st.rerun()
2199
-
2200
- # Display game scenario
2201
- st.subheader("🌟 Game Scenario")
2202
- st.markdown(f'<div class="game-card">{st.session_state.game_scenario}</div>', unsafe_allow_html=True)
2203
-
2204
- # Display game preview
2205
- st.subheader("🖼️ Game Preview")
2206
- if st.session_state.game_preview:
2207
- st.image(st.session_state.game_preview, use_container_width=True)
2208
- else:
2209
- st.warning("Game preview couldn't be generated. Showing example instead.")
2210
- st.image("https://i.imgur.com/7zQY1eE.gif", use_container_width=True)
2211
-
2212
- # Game explanation
2213
- st.subheader("📚 How This Game Teaches Coding")
2214
- st.markdown(f'<div class="game-card">{st.session_state.game_explanation}</div>', unsafe_allow_html=True)
2215
-
2216
- # Play instructions
2217
- st.subheader("▶️ How to Play")
2218
- st.markdown("""
2219
- <div class="game-card">
2220
- <ol>
2221
- <li>Download the game code from the <b>Game Code</b> tab</li>
2222
- <li>Install Python from <a href="https://python.org">python.org</a></li>
2223
- <li>Install PyGame: <code>pip install pygame</code></li>
2224
- <li>Run the game: <code>python your_game.py</code></li>
2225
- <li>Use arrow keys to move your character!</li>
2226
- </ol>
2227
- </div>
2228
- """, unsafe_allow_html=True)
2229
-
2230
- if st.button("Learn Coding Concepts", use_container_width=True):
2231
- st.session_state.active_tab = "concepts"
2232
- st.rerun()
2233
-
2234
- # Concepts tab
2235
- elif st.session_state.active_tab == "concepts":
2236
- st.header("🔍 Coding Concepts in Your Game")
2237
- st.subheader("Your game teaches these programming concepts:")
2238
-
2239
- if not st.session_state.concepts:
2240
- st.warning("No concepts detected in your story! Try adding words like '3 times', 'if', or 'collect'.")
2241
- else:
2242
- for concept in st.session_state.concepts:
2243
- if concept in CONCEPTS:
2244
- details = CONCEPTS[concept]
2245
- st.markdown(f"""
2246
- <div class="concept-card" style="border-left: 5px solid {details['color']};">
2247
- <div style="display:flex; align-items:center; gap:15px;">
2248
- <span style="font-size:36px;">{details['emoji']}</span>
2249
- <h3 style="color:{details['color']};">{details['name']}</h3>
2250
- </div>
2251
- <p>{details['description']}</p>
2252
- <p><b>In your game:</b> {details['game_example']}</p>
2253
- <pre style="background:#f0f0f0; padding:10px; border-radius:8px;">{details['example']}</pre>
2254
- </div>
2255
- """, unsafe_allow_html=True)
2256
-
2257
- if st.button("See the Game Code", use_container_width=True):
2258
- st.session_state.active_tab = "code"
2259
- st.rerun()
2260
-
2261
- # Code tab
2262
- elif st.session_state.active_tab == "code":
2263
- st.header("💻 Game Code")
2264
- st.write("Here's the Python code for your game. Download it and run on your computer!")
2265
-
2266
- if st.session_state.game_code:
2267
- # Display code with syntax highlighting
2268
- st.subheader("Your Game Code")
2269
- st.code(st.session_state.game_code, language="python")
2270
-
2271
- # Download button
2272
- st.download_button(
2273
- label="📥 Download Game Code",
2274
- data=st.session_state.game_code,
2275
- file_name="story_game.py",
2276
- mime="text/python",
2277
- use_container_width=True
2278
- )
2279
-
2280
- # Game running instructions
2281
- st.subheader("🖥️ How to Run Your Game")
2282
- st.markdown("""
2283
- <div class="game-card">
2284
- <ol>
2285
- <li>Install Python from <a href="https://python.org">python.org</a></li>
2286
- <li>Install PyGame: Open command prompt and type <code>pip install pygame</code></li>
2287
- <li>Save the game code to a file named <code>my_game.py</code></li>
2288
- <li>Run the game: <code>python my_game.py</code></li>
2289
- <li>Use arrow keys to play!</li>
2290
- </ol>
2291
- </div>
2292
- """, unsafe_allow_html=True)
2293
-
2294
- # What to expect
2295
- st.subheader("🎮 What to Expect When Playing")
2296
- st.markdown("""
2297
- <div class="game-card">
2298
- <ul>
2299
- <li>Move your character (red square) with arrow keys</li>
2300
- <li>Collect the green stars to increase your score</li>
2301
- <li>Avoid the brown obstacles</li>
2302
- <li>See how programming concepts make the game work!</li>
2303
- </ul>
2304
- </div>
2305
- """, unsafe_allow_html=True)
2306
- else:
2307
- st.warning("No game code generated yet!")
2308
-
2309
- if st.button("Create Another Story!", use_container_width=True):
2310
- st.session_state.active_tab = "story"
2311
- st.rerun()
2312
-
2313
- if __name__ == "__main__":
2314
- main()# app.py - Game-Based Learning Version
2315
- import streamlit as st
2316
- import os
2317
- import time
2318
- import random
2319
- import json
2320
- import base64
2321
- import requests
2322
- import re
2323
- from PIL import Image
2324
- import io
2325
- import matplotlib.pyplot as plt
2326
- from groq import Groq
2327
- from transformers import pipeline
2328
- import torch
2329
-
2330
- # Configure Streamlit page
2331
- st.set_page_config(
2332
- page_title="StoryCoder - Learn Coding Through Games",
2333
- page_icon="🎮",
2334
- layout="wide",
2335
- initial_sidebar_state="expanded"
2336
- )
2337
-
2338
- # Custom CSS for game-themed UI
2339
- st.markdown("""
2340
- <style>
2341
- @import url('https://fonts.googleapis.com/css2?family=Fredoka+One&family=Comic+Neue:wght@700&display=swap');
2342
-
2343
- :root {
2344
- --primary: #FF6B6B;
2345
- --secondary: #4ECDC4;
2346
- --accent: #FFD166;
2347
- --dark: #1A535C;
2348
- --light: #F7FFF7;
2349
- --game-blue: #118AB2;
2350
- --game-purple: #9B5DE5;
2351
- }
2352
-
2353
- body {
2354
- background: linear-gradient(135deg, #E8F4F8 0%, #FFDEE9 100%);
2355
- font-family: 'Comic Neue', cursive;
2356
- }
2357
-
2358
- .stApp {
2359
- background: url('https://www.transparenttextures.com/patterns/cartographer.png');
2360
- }
2361
-
2362
- .game-card {
2363
- background-color: white;
2364
- border-radius: 20px;
2365
- padding: 25px;
2366
- box-shadow: 0 8px 32px rgba(26, 83, 92, 0.2);
2367
- border: 4px solid var(--game-purple);
2368
- margin-bottom: 25px;
2369
- transition: all 0.3s;
2370
- }
2371
-
2372
- .game-card:hover {
2373
- transform: translateY(-5px);
2374
- box-shadow: 0 12px 24px rgba(26, 83, 92, 0.3);
2375
- }
2376
-
2377
- .header {
2378
- color: var(--dark);
2379
- font-family: 'Fredoka One', cursive;
2380
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
2381
- }
2382
-
2383
- .concept-card {
2384
- background: linear-gradient(145deg, #ffffff, #f0f0f0);
2385
- border-radius: 15px;
2386
- padding: 15px;
2387
- margin: 10px 0;
2388
- border-left: 5px solid var(--secondary);
2389
- box-shadow: 0 4px 12px rgba(0,0,0,0.1);
2390
- }
2391
-
2392
- .stButton>button {
2393
- background: linear-gradient(45deg, var(--game-purple), var(--game-blue));
2394
- color: white;
2395
- border-radius: 50px;
2396
- padding: 12px 28px;
2397
- font-weight: bold;
2398
- font-size: 20px;
2399
- border: none;
2400
- transition: all 0.3s;
2401
- font-family: 'Fredoka One', cursive;
2402
- }
2403
-
2404
- .stButton>button:hover {
2405
- transform: scale(1.05);
2406
- box-shadow: 0 8px 16px rgba(0,0,0,0.2);
2407
- }
2408
-
2409
- .stTextInput>div>div>input {
2410
- border-radius: 20px;
2411
- padding: 14px;
2412
- border: 3px solid var(--accent);
2413
- font-size: 18px;
2414
- }
2415
-
2416
- .tabs {
2417
- display: flex;
2418
- gap: 10px;
2419
- margin-bottom: 20px;
2420
- overflow-x: auto;
2421
- background: rgba(255,255,255,0.7);
2422
- padding: 10px;
2423
- border-radius: 20px;
2424
- }
2425
-
2426
- .tab {
2427
- padding: 12px 24px;
2428
- background-color: var(--accent);
2429
- border-radius: 15px;
2430
- cursor: pointer;
2431
- font-weight: bold;
2432
- white-space: nowrap;
2433
- font-family: 'Fredoka One', cursive;
2434
- font-size: 18px;
2435
- transition: all 0.3s;
2436
- }
2437
-
2438
- .tab.active {
2439
- background: linear-gradient(45deg, var(--game-purple), var(--game-blue));
2440
- color: white;
2441
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
2442
- }
2443
-
2444
- .game-preview {
2445
- border: 4px solid var(--game-blue);
2446
- border-radius: 20px;
2447
- overflow: hidden;
2448
- background: linear-gradient(135deg, #a2d2ff, #bde0fe);
2449
- padding: 20px;
2450
- margin: 20px 0;
2451
- }
2452
-
2453
- .character {
2454
- font-size: 64px;
2455
- text-align: center;
2456
- margin: 20px 0;
2457
- text-shadow: 4px 4px 8px rgba(0,0,0,0.2);
2458
- }
2459
-
2460
- .game-container {
2461
- background: rgba(255,255,255,0.9);
2462
- border-radius: 20px;
2463
- padding: 30px;
2464
- box-shadow: 0 8px 32px rgba(0,0,0,0.1);
2465
- margin: 20px 0;
2466
- }
2467
-
2468
- .code-block {
2469
- background: #2b2d42;
2470
- color: #f8f9fa;
2471
- border-radius: 15px;
2472
- padding: 20px;
2473
- font-family: 'Courier New', monospace;
2474
- overflow-x: auto;
2475
- margin: 20px 0;
2476
- }
2477
-
2478
- .concept-emoji {
2479
- font-size: 36px;
2480
- margin-right: 15px;
2481
- vertical-align: middle;
2482
- }
2483
-
2484
- .game-title {
2485
- font-family: 'Fredoka One', cursive;
2486
- color: var(--game-purple);
2487
- text-align: center;
2488
- font-size: 32px;
2489
- margin-bottom: 20px;
2490
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
2491
- }
2492
-
2493
- @media (max-width: 768px) {
2494
- .tabs {
2495
- flex-wrap: wrap;
2496
- }
2497
-
2498
- .character {
2499
- font-size: 48px;
2500
- }
2501
- }
2502
- </style>
2503
- """, unsafe_allow_html=True)
2504
-
2505
- # Initialize session state
2506
- def init_session_state():
2507
- if 'story' not in st.session_state:
2508
- st.session_state.story = ""
2509
- if 'concepts' not in st.session_state:
2510
- st.session_state.concepts = []
2511
- if 'game_scenario' not in st.session_state:
2512
- st.session_state.game_scenario = ""
2513
- if 'game_code' not in st.session_state:
2514
- st.session_state.game_code = ""
2515
- if 'game_explanation' not in st.session_state:
2516
- st.session_state.game_explanation = ""
2517
- if 'game_preview' not in st.session_state:
2518
- st.session_state.game_preview = ""
2519
- if 'active_tab' not in st.session_state:
2520
- st.session_state.active_tab = "story"
2521
- if 'loading' not in st.session_state:
2522
- st.session_state.loading = False
2523
-
2524
- # Concept database
2525
- CONCEPTS = {
2526
- "loop": {
2527
- "name": "Loop",
2528
- "emoji": "🔄",
2529
- "description": "Loops repeat actions multiple times",
2530
- "example": "for i in range(5):\n print('Hello!')",
2531
- "color": "#FF9E6D",
2532
- "game_example": "Repeating a jump 5 times to cross a river"
2533
- },
2534
- "conditional": {
2535
- "name": "Conditional",
2536
- "emoji": "❓",
2537
- "description": "Conditionals make decisions in code",
2538
- "example": "if sunny:\n go_outside()\nelse:\n stay_inside()",
2539
- "color": "#4ECDC4",
2540
- "game_example": "Choosing different paths based on obstacles"
2541
- },
2542
- "function": {
2543
- "name": "Function",
2544
- "emoji": "✨",
2545
- "description": "Functions are reusable blocks of code",
2546
- "example": "def greet(name):\n print(f'Hello {name}!')",
2547
- "color": "#FFD166",
2548
- "game_example": "Creating a jump function used multiple times"
2549
- },
2550
- "variable": {
2551
- "name": "Variable",
2552
- "emoji": "📦",
2553
- "description": "Variables store information",
2554
- "example": "score = 10\nplayer = 'Alex'",
2555
- "color": "#FF6B6B",
2556
- "game_example": "Keeping track of collected stars"
2557
- },
2558
- "list": {
2559
- "name": "List",
2560
- "emoji": "📝",
2561
- "description": "Lists store collections of items",
2562
- "example": "fruits = ['apple', 'banana', 'orange']",
2563
- "color": "#1A535C",
2564
- "game_example": "Storing collected treasures in a backpack"
2565
- }
2566
- }
2567
-
2568
- # Initialize Groq client
2569
- def get_groq_client():
2570
- try:
2571
- # Use a free proxy for Groq API access
2572
- return Groq(api_key="free-proxy-key", base_url="https://api.groq.com/openai/v1")
2573
- except:
2574
- st.error("Could not initialize Groq client. Using fallback method.")
2575
- return None
2576
-
2577
- # Analyze story and extract concepts
2578
- def analyze_story(story):
2579
- """Analyze story and identify programming concepts"""
2580
- story_lower = story.lower()
2581
- detected_concepts = []
2582
-
2583
- # Check for loops
2584
- if any(word in story_lower for word in ["times", "repeat", "again", "multiple"]):
2585
- detected_concepts.append("loop")
2586
-
2587
- # Check for conditionals
2588
- if any(word in story_lower for word in ["if", "when", "unless", "whether", "decide"]):
2589
- detected_concepts.append("conditional")
2590
-
2591
- # Check for functions
2592
- if any(word in story_lower for word in ["make", "create", "do", "perform", "cast"]):
2593
- detected_concepts.append("function")
2594
-
2595
- # Check for variables
2596
- if any(word in story_lower for word in ["is", "has", "set to", "value", "score"]):
2597
- detected_concepts.append("variable")
2598
-
2599
- # Check for lists
2600
- if any(word in story_lower for word in ["and", "many", "several", "collection", "items"]):
2601
- detected_concepts.append("list")
2602
-
2603
- return list(set(detected_concepts))
2604
-
2605
- # Generate game scenario using Groq
2606
- def generate_game_scenario(story, concepts):
2607
- """Generate a game scenario based on the story and concepts"""
2608
- try:
2609
- # Use Groq API for fast response
2610
- client = get_groq_client()
2611
- if client:
2612
- system_prompt = (
2613
- "You are an expert in creating educational games for children. "
2614
- "Create a simple 3D game scenario based on the child's story. "
2615
- "The game should teach programming concepts through gameplay. "
2616
- "Structure your response with:\n"
2617
- "Game Title: ...\n"
2618
- "Game Objective: ...\n"
2619
- "Characters: ...\n"
2620
- "Game Mechanics: ...\n"
2621
- "Coding Concepts: Explain how these programming concepts are used: " + ", ".join(concepts) + "\n"
2622
- "Visual Description: Describe the game world visually\n"
2623
- "Keep it under 200 words and suitable for children aged 6-12."
2624
- )
2625
-
2626
- response = client.chat.completions.create(
2627
- model="llama3-70b-8192",
2628
- messages=[
2629
- {"role": "system", "content": system_prompt},
2630
- {"role": "user", "content": story}
2631
- ],
2632
- temperature=0.7,
2633
- max_tokens=500
2634
- )
2635
- return response.choices[0].message.content
2636
- except Exception as e:
2637
- st.error(f"Groq API error: {str(e)}")
2638
-
2639
- # Fallback to Hugging Face model
2640
- try:
2641
- generator = pipeline("text-generation", model="HuggingFaceH4/zephyr-7b-beta")
2642
- prompt = (
2643
- f"Create a children's educational game based on this story: {story}\n"
2644
- f"Game should teach these programming concepts: {', '.join(concepts)}\n"
2645
- "Structure response with:\n"
2646
- "Game Title: ...\n"
2647
- "Game Objective: ...\n"
2648
- "Characters: ...\n"
2649
- "Game Mechanics: ...\n"
2650
- "Coding Concepts: ...\n"
2651
- "Visual Description: ...\n"
2652
- )
2653
- result = generator(prompt, max_length=400, do_sample=True, temperature=0.7)
2654
- return result[0]['generated_text']
2655
- except:
2656
- # Final fallback
2657
- return (
2658
- f"Game Title: {story[:20]} Adventure\n"
2659
- f"Game Objective: Complete challenges based on the story: {story[:100]}...\n"
2660
- "Characters: Hero character based on the story\n"
2661
- "Game Mechanics: Navigate through levels, collect items, solve puzzles\n"
2662
- f"Coding Concepts: This game teaches {', '.join(concepts)} through gameplay\n"
2663
- "Visual Description: Colorful 3D world with characters and obstacles"
2664
- )
2665
-
2666
- # Generate game code explanation
2667
- def generate_game_explanation(story, concepts, game_scenario):
2668
- """Generate explanation of game code"""
2669
- try:
2670
- client = get_groq_client()
2671
- if client:
2672
- system_prompt = (
2673
- "Explain how the game code implements the programming concepts in a way "
2674
- "a child can understand. Use simple analogies and relate to the story. "
2675
- "Structure your response with:\n"
2676
- "Introduction: ...\n"
2677
- "Concept 1: ...\n"
2678
- "Concept 2: ...\n"
2679
- "Conclusion: ...\n"
2680
- "Keep it under 300 words and fun for kids."
2681
- )
2682
-
2683
- response = client.chat.completions.create(
2684
- model="llama3-70b-8192",
2685
- messages=[
2686
- {"role": "system", "content": system_prompt},
2687
- {"role": "user", "content": f"Story: {story}\nGame Scenario: {game_scenario}\nConcepts: {', '.join(concepts)}"}
2688
- ],
2689
- temperature=0.7,
2690
- max_tokens=600
2691
- )
2692
- return response.choices[0].message.content
2693
- except:
2694
- pass
2695
-
2696
- # Fallback
2697
- concept_explanations = "\n".join(
2698
- [f"- {CONCEPTS[c]['name']}: {CONCEPTS[c]['game_example']}" for c in concepts]
2699
- )
2700
- return (
2701
- f"In this game based on your story '{story[:20]}...', we use programming concepts to make it work:\n"
2702
- f"{concept_explanations}\n\n"
2703
- "The code brings your story to life in a 3D game world!"
2704
- )
2705
-
2706
- # Generate simple game code
2707
- def generate_game_code(story, concepts):
2708
- """Generate simple PyGame code for the game"""
2709
- # This is a template - in a real app, this would be dynamically generated
2710
- return f"""
2711
- # {story[:30]} Adventure Game
2712
- import pygame
2713
- import random
2714
-
2715
- # Initialize pygame
2716
- pygame.init()
2717
-
2718
- # Game setup
2719
- WIDTH, HEIGHT = 800, 600
2720
- screen = pygame.display.set_mode((WIDTH, HEIGHT))
2721
- pygame.display.set_caption("{story[:20]} Adventure")
2722
- clock = pygame.time.Clock()
2723
-
2724
- # Colors
2725
- BACKGROUND = (173, 216, 230) # Light blue
2726
- PLAYER_COLOR = (255, 0, 0) # Red
2727
- GOAL_COLOR = (0, 255, 0) # Green
2728
- OBSTACLE_COLOR = (139, 69, 19) # Brown
2729
-
2730
- # Player setup
2731
- player_size = 50
2732
- player_x = 100
2733
- player_y = HEIGHT // 2
2734
- player_speed = 5
2735
-
2736
- # Goal setup
2737
- goal_size = 40
2738
- goal_x = WIDTH - 150
2739
- goal_y = HEIGHT // 2
2740
-
2741
- # Variables concept: Tracking score
2742
- score = 0
2743
- font = pygame.font.SysFont(None, 36)
2744
-
2745
- # List concept: Creating obstacles
2746
- obstacles = []
2747
- for i in range(5):
2748
- obstacles.append([
2749
- random.randint(200, WIDTH - 100),
2750
- random.randint(50, HEIGHT - 100),
2751
- random.randint(20, 50),
2752
- random.randint(20, 50)
2753
- ])
2754
-
2755
- # Game loop
2756
- running = True
2757
- while running:
2758
- # Event handling
2759
- for event in pygame.event.get():
2760
- if event.type == pygame.QUIT:
2761
- running = False
2762
-
2763
- # Player movement
2764
- keys = pygame.key.get_pressed()
2765
- if keys[pygame.K_UP]:
2766
- player_y -= player_speed
2767
- if keys[pygame.K_DOWN]:
2768
- player_y += player_speed
2769
- if keys[pygame.K_LEFT]:
2770
- player_x -= player_speed
2771
- if keys[pygame.K_RIGHT]:
2772
- player_x += player_speed
2773
-
2774
- # Boundary checking
2775
- player_x = max(0, min(WIDTH - player_size, player_x))
2776
- player_y = max(0, min(HEIGHT - player_size, player_y))
2777
-
2778
- # Collision detection with goal
2779
- player_rect = pygame.Rect(player_x, player_y, player_size, player_size)
2780
- goal_rect = pygame.Rect(goal_x, goal_y, goal_size, goal_size)
2781
-
2782
- # Conditional concept: Check for collision
2783
- if player_rect.colliderect(goal_rect):
2784
- # Function concept: Increase score
2785
- score += 1
2786
- # Move goal to new position
2787
- goal_x = random.randint(100, WIDTH - 100)
2788
- goal_y = random.randint(50, HEIGHT - 100)
2789
-
2790
- # Drawing
2791
- screen.fill(BACKGROUND)
2792
-
2793
- # Draw obstacles
2794
- for obstacle in obstacles:
2795
- pygame.draw.rect(screen, OBSTACLE_COLOR,
2796
- (obstacle[0], obstacle[1], obstacle[2], obstacle[3]))
2797
-
2798
- # Draw player and goal
2799
- pygame.draw.rect(screen, PLAYER_COLOR,
2800
- (player_x, player_y, player_size, player_size))
2801
- pygame.draw.rect(screen, GOAL_COLOR,
2802
- (goal_x, goal_y, goal_size, goal_size))
2803
-
2804
- # Display score
2805
- score_text = font.render(f"Stars: {{score}}", True, (0, 0, 0))
2806
- screen.blit(score_text, (20, 20))
2807
 
2808
  # Update display
2809
  pygame.display.flip()
@@ -2990,7 +673,7 @@ def main():
2990
  <div class="game-card">
2991
  <ol>
2992
  <li>Download the game code from the <b>Game Code</b> tab</li>
2993
- <li>Install Python from <a href="https://python.org">python.org</a></li>
2994
  <li>Install PyGame: <code>pip install pygame</code></li>
2995
  <li>Run the game: <code>python your_game.py</code></li>
2996
  <li>Use arrow keys to move your character!</li>
@@ -3053,7 +736,7 @@ def main():
3053
  st.markdown("""
3054
  <div class="game-card">
3055
  <ol>
3056
- <li>Install Python from <a href="https://python.org">python.org</a></li>
3057
  <li>Install PyGame: Open command prompt and type <code>pip install pygame</code></li>
3058
  <li>Save the game code to a file named <code>my_game.py</code></li>
3059
  <li>Run the game: <code>python my_game.py</code></li>
 
1
+ # app.py - Game-Based Learning with Free Models
2
  import streamlit as st
3
  import os
4
  import time
 
10
  from PIL import Image
11
  import io
12
  import matplotlib.pyplot as plt
 
13
  from transformers import pipeline
14
  import torch
15
 
 
251
  }
252
  }
253
 
254
+ # Load models with caching
255
+ @st.cache_resource
256
+ def load_text_generator():
257
+ """Load a free text generation model"""
258
  try:
259
+ # Using a smaller model for better performance
260
+ return pipeline("text-generation", model="gpt2")
261
  except:
 
262
  return None
263
 
264
  # Analyze story and extract concepts
 
289
 
290
  return list(set(detected_concepts))
291
 
292
+ # Generate game scenario using free models
293
  def generate_game_scenario(story, concepts):
294
  """Generate a game scenario based on the story and concepts"""
295
  try:
296
+ # Create prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  prompt = (
298
  f"Create a children's educational game based on this story: {story}\n"
299
  f"Game should teach these programming concepts: {', '.join(concepts)}\n"
 
305
  "Coding Concepts: ...\n"
306
  "Visual Description: ...\n"
307
  )
308
+
309
+ # Generate with free model
310
+ generator = load_text_generator()
311
+ if generator:
312
+ result = generator(
313
+ prompt,
314
+ max_length=400,
315
+ do_sample=True,
316
+ temperature=0.7,
317
+ num_return_sequences=1
318
+ )
319
+ return result[0]['generated_text']
320
+ except Exception as e:
321
+ st.error(f"Text generation error: {str(e)}")
322
+
323
+ # Fallback scenario
324
+ concept_names = [CONCEPTS[c]["name"] for c in concepts]
325
+ return (
326
+ f"Game Title: {story[:20]} Adventure\n\n"
327
+ f"Game Objective: Complete challenges based on the story: {story[:100]}...\n\n"
328
+ "Characters: Hero character based on the story\n\n"
329
+ "Game Mechanics: Navigate through levels, collect items, solve puzzles\n\n"
330
+ f"Coding Concepts: This game teaches {', '.join(concept_names)} through gameplay\n\n"
331
+ "Visual Description: Colorful 3D world with characters and obstacles"
332
+ )
333
 
334
  # Generate game code explanation
335
  def generate_game_explanation(story, concepts, game_scenario):
336
  """Generate explanation of game code"""
337
  try:
338
+ # Create prompt
339
+ prompt = (
340
+ f"Explain how a game based on this story teaches programming concepts to children: {story}\n"
341
+ f"Game Scenario: {game_scenario}\n"
342
+ f"Concepts: {', '.join(concepts)}\n"
343
+ "Use simple language and analogies for kids aged 6-12."
344
+ )
345
+
346
+ # Generate with free model
347
+ generator = load_text_generator()
348
+ if generator:
349
+ result = generator(
350
+ prompt,
351
+ max_length=300,
352
+ do_sample=True,
 
 
 
 
353
  temperature=0.7,
354
+ num_return_sequences=1
355
  )
356
+ return result[0]['generated_text']
357
  except:
358
  pass
359
 
360
+ # Fallback explanation
361
  concept_explanations = "\n".join(
362
  [f"- {CONCEPTS[c]['name']}: {CONCEPTS[c]['game_example']}" for c in concepts]
363
  )
 
370
  # Generate simple game code
371
  def generate_game_code(story, concepts):
372
  """Generate simple PyGame code for the game"""
373
+ # Extract game elements from story
374
+ character = "hero"
375
+ goal = "treasure"
376
+ obstacles = ["rock", "tree", "river"]
377
+
378
+ if "knight" in story.lower():
379
+ character = "knight"
380
+ goal = "dragon"
381
+ elif "space" in story.lower():
382
+ character = "astronaut"
383
+ goal = "planet"
384
+ elif "jungle" in story.lower():
385
+ character = "explorer"
386
+ goal = "temple"
387
+
388
+ # Generate dynamic game code
389
  return f"""
390
  # {story[:30]} Adventure Game
391
  import pygame
 
484
  score_text = font.render(f"Stars: {{score}}", True, (0, 0, 0))
485
  screen.blit(score_text, (20, 20))
486
 
487
+ # Display character type
488
+ char_text = font.render(f"Character: {character.title()}", True, (0, 0, 0))
489
+ screen.blit(char_text, (20, 60))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
 
491
  # Update display
492
  pygame.display.flip()
 
673
  <div class="game-card">
674
  <ol>
675
  <li>Download the game code from the <b>Game Code</b> tab</li>
676
+ <li>Install Python from <a href="https://python.org" target="_blank">python.org</a></li>
677
  <li>Install PyGame: <code>pip install pygame</code></li>
678
  <li>Run the game: <code>python your_game.py</code></li>
679
  <li>Use arrow keys to move your character!</li>
 
736
  st.markdown("""
737
  <div class="game-card">
738
  <ol>
739
+ <li>Install Python from <a href="https://python.org" target="_blank">python.org</a></li>
740
  <li>Install PyGame: Open command prompt and type <code>pip install pygame</code></li>
741
  <li>Save the game code to a file named <code>my_game.py</code></li>
742
  <li>Run the game: <code>python my_game.py</code></li>