File size: 6,135 Bytes
7e3c169
7eb93c1
 
80e337e
6f65240
7eb93c1
e025a9a
0e49c7f
7eb93c1
6b8a0a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e025a9a
7eb93c1
e025a9a
 
7eb93c1
 
e025a9a
6f65240
6b8a0a7
 
 
 
 
ef526b0
6b8a0a7
 
6f65240
6b8a0a7
7eb93c1
 
e025a9a
3867c2c
7eb93c1
 
e025a9a
3867c2c
e025a9a
 
 
 
 
 
 
 
adbce6c
 
85c7252
80e337e
041a11e
85c7252
80e337e
 
516f6fa
80e337e
adbce6c
 
 
3867c2c
 
6f65240
3867c2c
6b8a0a7
 
 
 
 
 
 
 
6f65240
7eb93c1
adbce6c
 
 
 
 
85c7252
516f6fa
85c7252
516f6fa
 
e025a9a
adbce6c
e025a9a
3867c2c
e025a9a
3867c2c
e025a9a
 
516f6fa
e025a9a
adbce6c
e025a9a
80e337e
adbce6c
7eb93c1
adbce6c
e025a9a
3867c2c
 
e025a9a
adbce6c
 
 
7e3c169
e025a9a
 
3867c2c
e025a9a
 
 
 
 
 
7e3c169
3867c2c
6f65240
7eb93c1
85c7252
 
7e3c169
85c7252
7eb93c1
6f65240
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import time
from langchain_groq import ChatGroq
import streamlit as st
from crewai import Agent
import os

# Initialize LLM
llm = ChatGroq(temperature=0.4, model_name="meta-llama/llama-4-maverick-17b-128e-instruct")

# File to store history
HISTORY_FILE = "history.txt"

# Load question history from file
def load_history():
    if os.path.exists(HISTORY_FILE):
        with open(HISTORY_FILE, "r") as f:
            return [line.strip() for line in f.readlines()]
    return []

# Save question history to file
def save_history(history):
    with open(HISTORY_FILE, "w") as f:
        for question in history:
            f.write(question + "\n")

# Initialize session state
if "level" not in st.session_state:
    st.session_state.level = 1
    st.session_state.points = 0
    st.session_state.history = load_history()  # Load history at startup
    st.session_state.questions_answered = 0
    st.session_state.current_question = None
    st.session_state.hint = None
    st.session_state.lives = 3

# Define Agents
class NarratorAgent(Agent):
    def act(self, level):
        return f"Welcome to Level {level}, prepare to face your next challenge!"

class QuestionAgent(Agent):
    def act(self, level, history):
        """Generate a unique question that is not in history"""
        for _ in range(10):  # Try multiple times to get a unique question
            question = llm.invoke(
                f"Generate a general knowledge question for a Q and A game. The player is at level {level}. "
                f"Avoid repeating questions from this list: {history}. "
                f"Do not include MCQs, only a single general knowledge question."
                f"Only include the question nothing else no any extra message"
            ).content.strip()
            if question and question not in history:
                return question
        return "No new questions available. Try again later."

class HintAgent(Agent):
    def act(self, level, question):
        return llm.invoke(f"Generate a hint for this question: {question}. The player is at level {level}, so don't reveal too much detail.").content

class AnswerCheckerAgent(Agent):
    def act(self, question, answer):
        return llm.invoke(f"Check if the user's answer: '{answer}' is correct for the question: '{question}'. Only respond with 'yes' or 'no'.").content.lower().strip()

# Instantiate agents
narrator = NarratorAgent(role="Narrator", goal="Guide the story forward", backstory="Knows all details of the world and its characters.")
questioner = QuestionAgent(role="Questioner", goal="Generate a general knowledge question", backstory="Knows all general knowledge.")
hinter = HintAgent(role="Hinter", goal="Provide hints about the question", backstory="Knows the correct answer but gives limited hints.")
validator = AnswerCheckerAgent(role="Validator", goal="Check if the answer is correct", backstory="Knows the correct answer.")

# Streamlit App
st.title("🏰 Knowledge Dungeon 🏰")

# Sidebar for Level, Points & Lives Display
st.sidebar.header("πŸ“œ Game Stats")
st.sidebar.warning('Type "hint" to get hints from Gandalf ✨')

st.sidebar.write(f"**πŸ† Level:** {st.session_state.level}")
st.sidebar.write(f"**πŸ’° Points:** {st.session_state.points}")
st.sidebar.write(f"**❀️ Lives:** {st.session_state.lives}")

MAX_LEVEL = 10
QUESTIONS_PER_LEVEL = 3
POINTS_PER_CORRECT = 10

def generate_new_question():
    """Generates a unique new question and stores it in session state."""
    question = questioner.act(st.session_state.level, st.session_state.history)
    
    if question != "No new questions available. Try again later.":
        st.session_state.current_question = question
        st.session_state.history.append(question)
        st.session_state.hint = hinter.act(st.session_state.level, question)
        save_history(st.session_state.history)  # Save immediately to prevent duplicates
    else:
        st.session_state.current_question = "No more questions available!"

def main():
    level = st.session_state.level

    if level > MAX_LEVEL:
        st.success("πŸŽ‰ Congratulations! You have won the game! πŸŽ‰")
        st.stop()
    
    if st.session_state.lives <= 0:
        st.error("πŸ’€ You have lost all your lives! Game Over!")
        st.stop()

    # Display Narration
    st.write(f"πŸ“œ {narrator.act(level)}")

    # Generate a new question if needed
    if not st.session_state.current_question:
        generate_new_question()

    # Display the question
    st.write(f"**Sauron:** A feeble mortal dares to challenge me? Hah! Answer this question, or be doomed to eternal failure!")
    st.write(f"πŸ”Ή {st.session_state.current_question}")

    # User input
    answer = st.text_input("Your Answer:")

    if st.button("Submit Answer"):
        if answer.lower().strip() == "hint":
            st.info(f"πŸ’‘ Hint: {st.session_state.hint}")
        elif answer.strip():
            response = validator.act(st.session_state.current_question, answer)
            if response in ['yes', 'yes.']:
                st.success("βœ… Correct! You defeated the enemy.")
                st.session_state.points += POINTS_PER_CORRECT
                st.session_state.questions_answered += 1
                time.sleep(3)
                # Move to next level if necessary
                if st.session_state.questions_answered >= QUESTIONS_PER_LEVEL:
                    if st.session_state.level == MAX_LEVEL:
                        st.success("πŸŽ‰ Congratulations! You have won the game! πŸŽ‰")
                        st.stop()
                    else:
                        st.session_state.level += 1
                        st.session_state.questions_answered = 0
                        st.success(f"πŸ”Ί Level Up! Welcome to Level {st.session_state.level}.")
                        time.sleep(3)
                generate_new_question()
                st.rerun()
            else:
                st.error("❌ Wrong answer! Try again.")
                st.session_state.lives -= 1
                time.sleep(3)
                st.rerun()  # Force refresh to update lives in sidebar

main()