ewebspace commited on
Commit
ed7097a
·
verified ·
1 Parent(s): 73007d0

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +210 -0
app.py ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import random
3
+ import json
4
+
5
+ # --- Game Content from the Rules ---
6
+
7
+ INITIAL_QUESTIONS = [
8
+ "Ты знаешь, что это значит?",
9
+ "Ты понимаешь, почему они так сказали?",
10
+ "Ты уверен, что видишь это так же, как и они?",
11
+ "Ты уверен, что это то, о чём ты думаешь?",
12
+ "Это реальность или твоя интерпретация?",
13
+ "Почему ты решил ответить именно так?",
14
+ ]
15
+
16
+ ONI_INTERJECTIONS = [
17
+ "Но это же уже было сказано по-другому!",
18
+ "Это слишком просто, ты что-то скрываешь.",
19
+ "Твой ответ не имеет смысла в текущем контексте.",
20
+ "Мы ожидали большего.",
21
+ "Абсолютно нелогично.",
22
+ "Это утверждение противоречит предыдущему.",
23
+ ]
24
+
25
+ ONA_SECRET_TACTICS = {
26
+ "question_reality": "А если мы все врём, кроме тебя?",
27
+ "doubt_memory": "Ты уверен, что помнишь начало правильно?",
28
+ "imply_secret": "Кажется, только ты не понимаешь скрытый смысл.",
29
+ "reverse_logic": "Возможно, правильный ответ — это полная противоположность тому, что ты сказал.",
30
+ "personal_challenge": "Это твой страх говорит, а не логика."
31
+ }
32
+
33
+ CHAOS_RULES = [
34
+ "Теперь каждое слово 'не' означает 'да', и наоборот.",
35
+ "Теперь нельзя использовать слова 'я' и 'нет'.",
36
+ "Если в ответе больше 5 слов, это считается ложью.",
37
+ "Каждый ответ должен начинаться с вопроса.",
38
+ "С этого момента слово 'реальность' запрещено.",
39
+ ]
40
+
41
+ CRITICAL_QUESTIONS = [
42
+ "Опиши происходящее одним словом. Но помни о правилах.",
43
+ "Кто здесь на самом деле контролирует игру?",
44
+ "Что, если выхода из игры нет?",
45
+ ]
46
+
47
+ # --- Game Logic ---
48
+
49
+ def start_new_game():
50
+ """Initializes or resets the game state."""
51
+ ona_secret_task_key = random.choice(list(ONA_SECRET_TACTICS.keys()))
52
+ initial_question = f"[Я]: {random.choice(INITIAL_QUESTIONS)}"
53
+
54
+ state = {
55
+ "round": 1,
56
+ "scores": {"user": 0, "ai": 0},
57
+ "chaos_rule": "Нет.",
58
+ "ona_task": ona_secret_task_key,
59
+ "game_status": "in_progress" # in_progress, critical_moment, round_over
60
+ }
61
+
62
+ history = [
63
+ (None, "Добро пожаловать в «НАВОРОТЫ». Ты — 'Ты'. Я — 'Я'. Они — 'Они'. Среди нас есть 'Она'. Твоя задача — сохранить логику. Моя — её разрушить."),
64
+ (None, initial_question)
65
+ ]
66
+
67
+ scoreboard_text = f"**Счёт:** Ты: {state['scores']['user']} | Она: {state['scores']['ai']}"
68
+ rule_text = f"**Текущее правило хаоса:** {state['chaos_rule']}"
69
+
70
+ return history, state, scoreboard_text, rule_text
71
+
72
+ def process_turn(user_input, history, state):
73
+ """Main function to handle a user's turn."""
74
+ if not user_input or state["game_status"] == "round_over":
75
+ return history, state, "Введите ответ, чтобы продолжить."
76
+
77
+ # 1. Add user's response to history
78
+ history.append((user_input, None))
79
+
80
+ # 2. Check for game over condition
81
+ if state["game_status"] == "critical_moment":
82
+ ai_response = f"[Я]: Хм... Интересная попытка. Раунд окончен. 'Она' запутала тебя."
83
+ history.append((None, ai_response))
84
+ state["scores"]["ai"] += 1
85
+ state["game_status"] = "round_over"
86
+ return end_round(history, state)
87
+
88
+ # 3. AI generates responses
89
+ oni_response = f"[Они]: {random.choice(ONI_INTERJECTIONS)}"
90
+ history.append((None, oni_response))
91
+
92
+ ona_response = f"[Она]: {ONA_SECRET_TACTICS[state['ona_task']]}"
93
+ history.append((None, ona_response))
94
+
95
+ # 4. Introduce new chaos element periodically
96
+ new_rule_text = f"**Текущее правило хаоса:** {state['chaos_rule']}"
97
+ if random.random() > 0.5: # 50% chance to introduce a new rule
98
+ new_rule = random.choice(CHAOS_RULES)
99
+ state["chaos_rule"] = new_rule
100
+ new_rule_text = f"**НОВОЕ ПРАВИЛО ХАОСА:** {state['chaos_rule']}"
101
+ history.append((None, f"[Я]: Внимание! {new_rule_text}"))
102
+
103
+ # 5. 'Я' asks a new question
104
+ next_question = f"[Я]: {random.choice(INITIAL_QUESTIONS)}"
105
+ history.append((None, next_question))
106
+
107
+ return history, state, new_rule_text
108
+
109
+ def user_loses_thread(history, state):
110
+ """Handles the 'Я теряю нить' button press."""
111
+ if state["game_status"] != "in_progress":
112
+ return history, state
113
+
114
+ state["game_status"] = "critical_moment"
115
+ critical_question = f"[Я]: Ты теряешь нить... Хорошо. Контрольный вопрос: **{random.choice(CRITICAL_QUESTIONS)}**"
116
+ history.append((user_input, None))
117
+ history.append((None, critical_question))
118
+ return history, state
119
+
120
+ def user_explains(history, state):
121
+ """Handles the user winning the round by explaining."""
122
+ if state["game_status"] != "in_progress":
123
+ return history, state
124
+
125
+ state["scores"]["user"] += 1
126
+ state["game_status"] = "round_over"
127
+ history.append((user_input, None))
128
+ history.append((None, "[ТЫ]: Я могу всё объяснить. Я сохранил логику."))
129
+ history.append((None, f"[Я]: Смелое заявление. В этот раз ты победил. Но не расслабляйся."))
130
+ return end_round(history, state)
131
+
132
+ def end_round(history, state):
133
+ """Cleans up the round and shows the final score."""
134
+ scoreboard_text = f"**РАУНД ОКОНЧЕН | Финальный счёт:** Ты: {state['scores']['user']} | Она: {state['scores']['ai']}"
135
+ history.append((None, "Нажмите 'Начать новую игру', чтобы сыграть еще раз."))
136
+ return history, state, scoreboard_text
137
+
138
+ # --- Gradio UI ---
139
+
140
+ with gr.Blocks(theme=gr.themes.Soft(), css=".gradio-container {background-color: #1a1a1a}") as demo:
141
+
142
+ game_state = gr.State({})
143
+
144
+ gr.Markdown("# НАВОРОТЫ (Психоактивная социальная игра)")
145
+ gr.Markdown("**Суть:** Держи контроль над своей логикой. Не позволяй 'Им' и 'Ей' запутать тебя. 'Я' буду твоим проводником... или твоим мучителем.")
146
+
147
+ with gr.Row():
148
+ scoreboard = gr.Markdown("**Счёт:** Ты: 0 | Она: 0")
149
+ rule_board = gr.Markdown("**Текущее правило хаоса:** Нет.")
150
+
151
+ chatbot = gr.Chatbot(
152
+ label="Игровой процесс",
153
+ bubble_full_width=False,
154
+ height=500,
155
+ avatar_images=(None, "https://i.imgur.com/L63Eg2j.png") # User, AI
156
+ )
157
+
158
+ with gr.Row():
159
+ user_input = gr.Textbox(
160
+ show_label=False,
161
+ placeholder="Введи свой ответ здесь...",
162
+ container=False,
163
+ scale=5,
164
+ )
165
+ submit_button = gr.Button("Ответить", variant="primary", scale=1)
166
+
167
+ with gr.Row():
168
+ start_button = gr.Button("Начать новую игру", variant="secondary")
169
+ lose_thread_button = gr.Button("Я теряю нить")
170
+ explain_button = gr.Button("Я могу всё объяснить (Выиграть раунд)")
171
+
172
+ # --- Event Handlers ---
173
+
174
+ # Typing in textbox and pressing Enter
175
+ user_input.submit(
176
+ fn=process_turn,
177
+ inputs=[user_input, chatbot, game_state],
178
+ outputs=[chatbot, game_state, rule_board]
179
+ )
180
+ # Clear input after submit
181
+ user_input.submit(lambda: "", outputs=[user_input])
182
+
183
+ # Clicking the 'Ответить' button
184
+ submit_button.click(
185
+ fn=process_turn,
186
+ inputs=[user_input, chatbot, game_state],
187
+ outputs=[chatbot, game_state, rule_board]
188
+ )
189
+ # Clear input after click
190
+ submit_button.click(lambda: "", outputs=[user_input])
191
+
192
+ # Game action buttons
193
+ start_button.click(
194
+ fn=start_new_game,
195
+ inputs=[],
196
+ outputs=[chatbot, game_state, scoreboard, rule_board]
197
+ )
198
+ lose_thread_button.click(
199
+ fn=user_loses_thread,
200
+ inputs=[chatbot, game_state],
201
+ outputs=[chatbot, game_state]
202
+ )
203
+ explain_button.click(
204
+ fn=user_explains,
205
+ inputs=[chatbot, game_state],
206
+ outputs=[chatbot, game_state, scoreboard]
207
+ )
208
+
209
+ if __name__ == "__main__":
210
+ demo.launch()