import gradio as gr import random import json # --- Game Content from the Rules --- INITIAL_QUESTIONS = [ "Ты знаешь, что это значит?", "Ты понимаешь, почему они так сказали?", "Ты уверен, что видишь это так же, как и они?", "Ты уверен, что это то, о чём ты думаешь?", "Это реальность или твоя интерпретация?", "Почему ты решил ответить именно так?", ] ONI_INTERJECTIONS = [ "Но это же уже было сказано по-другому!", "Это слишком просто, ты что-то скрываешь.", "Твой ответ не имеет смысла в текущем контексте.", "Мы ожидали большего.", "Абсолютно нелогично.", "Это утверждение противоречит предыдущему.", ] ONA_SECRET_TACTICS = { "question_reality": "А если мы все врём, кроме тебя?", "doubt_memory": "Ты уверен, что помнишь начало правильно?", "imply_secret": "Кажется, только ты не понимаешь скрытый смысл.", "reverse_logic": "Возможно, правильный ответ — это полная противоположность тому, что ты сказал.", "personal_challenge": "Это твой страх говорит, а не логика." } CHAOS_RULES = [ "Теперь каждое слово 'не' означает 'да', и наоборот.", "Теперь нельзя использовать слова 'я' и 'нет'.", "Если в ответе больше 5 слов, это считается ложью.", "Каждый ответ должен начинаться с вопроса.", "С этого момента слово 'реальность' запрещено.", ] CRITICAL_QUESTIONS = [ "Опиши происходящее одним словом. Но помни о правилах.", "Кто здесь на самом деле контролирует игру?", "Что, если выхода из игры нет?", ] # --- Game Logic --- def start_new_game(): """Initializes or resets the game state.""" ona_secret_task_key = random.choice(list(ONA_SECRET_TACTICS.keys())) initial_question = f"[Я]: {random.choice(INITIAL_QUESTIONS)}" state = { "round": 1, "scores": {"user": 0, "ai": 0}, "chaos_rule": "Нет.", "ona_task": ona_secret_task_key, "game_status": "in_progress" # in_progress, critical_moment, round_over } history = [ (None, "Добро пожаловать в «НАВОРОТЫ». Ты — 'Ты'. Я — 'Я'. Они — 'Они'. Среди нас есть 'Она'. Твоя задача — сохранить логику. Моя — её разрушить."), (None, initial_question) ] scoreboard_text = f"**Счёт:** Ты: {state['scores']['user']} | Она: {state['scores']['ai']}" rule_text = f"**Текущее правило хаоса:** {state['chaos_rule']}" return history, state, scoreboard_text, rule_text def process_turn(user_input, history, state): """Main function to handle a user's turn.""" if not user_input or state["game_status"] == "round_over": return history, state, "Введите ответ, чтобы продолжить." # 1. Add user's response to history history.append((user_input, None)) # 2. Check for game over condition if state["game_status"] == "critical_moment": ai_response = f"[Я]: Хм... Интересная попытка. Раунд окончен. 'Она' запутала тебя." history.append((None, ai_response)) state["scores"]["ai"] += 1 state["game_status"] = "round_over" return end_round(history, state) # 3. AI generates responses oni_response = f"[Они]: {random.choice(ONI_INTERJECTIONS)}" history.append((None, oni_response)) ona_response = f"[Она]: {ONA_SECRET_TACTICS[state['ona_task']]}" history.append((None, ona_response)) # 4. Introduce new chaos element periodically new_rule_text = f"**Текущее правило хаоса:** {state['chaos_rule']}" if random.random() > 0.5: # 50% chance to introduce a new rule new_rule = random.choice(CHAOS_RULES) state["chaos_rule"] = new_rule new_rule_text = f"**НОВОЕ ПРАВИЛО ХАОСА:** {state['chaos_rule']}" history.append((None, f"[Я]: Внимание! {new_rule_text}")) # 5. 'Я' asks a new question next_question = f"[Я]: {random.choice(INITIAL_QUESTIONS)}" history.append((None, next_question)) return history, state, new_rule_text def user_loses_thread(history, state): """Handles the 'Я теряю нить' button press.""" if state["game_status"] != "in_progress": return history, state state["game_status"] = "critical_moment" critical_question = f"[Я]: Ты теряешь нить... Хорошо. Контрольный вопрос: **{random.choice(CRITICAL_QUESTIONS)}**" history.append((user_input, None)) history.append((None, critical_question)) return history, state def user_explains(history, state): """Handles the user winning the round by explaining.""" if state["game_status"] != "in_progress": return history, state state["scores"]["user"] += 1 state["game_status"] = "round_over" history.append((user_input, None)) history.append((None, "[ТЫ]: Я могу всё объяснить. Я сохранил логику.")) history.append((None, f"[Я]: Смелое заявление. В этот раз ты победил. Но не расслабляйся.")) return end_round(history, state) def end_round(history, state): """Cleans up the round and shows the final score.""" scoreboard_text = f"**РАУНД ОКОНЧЕН | Финальный счёт:** Ты: {state['scores']['user']} | Она: {state['scores']['ai']}" history.append((None, "Нажмите 'Начать новую игру', чтобы сыграть еще раз.")) return history, state, scoreboard_text # --- Gradio UI --- with gr.Blocks(theme=gr.themes.Soft(), css=".gradio-container {background-color: #1a1a1a}") as demo: game_state = gr.State({}) gr.Markdown("# НАВОРОТЫ (Психоактивная социальная игра)") gr.Markdown("**Суть:** Держи контроль над своей логикой. Не позволяй 'Им' и 'Ей' запутать тебя. 'Я' буду твоим проводником... или твоим мучителем.") with gr.Row(): scoreboard = gr.Markdown("**Счёт:** Ты: 0 | Она: 0") rule_board = gr.Markdown("**Текущее правило хаоса:** Нет.") chatbot = gr.Chatbot( label="Игровой процесс", bubble_full_width=False, height=500, avatar_images=(None, "https://i.imgur.com/L63Eg2j.png") # User, AI ) with gr.Row(): user_input = gr.Textbox( show_label=False, placeholder="Введи свой ответ здесь...", container=False, scale=5, ) submit_button = gr.Button("Ответить", variant="primary", scale=1) with gr.Row(): start_button = gr.Button("Начать новую игру", variant="secondary") lose_thread_button = gr.Button("Я теряю нить") explain_button = gr.Button("Я могу всё объяснить (Выиграть раунд)") # --- Event Handlers --- # Typing in textbox and pressing Enter user_input.submit( fn=process_turn, inputs=[user_input, chatbot, game_state], outputs=[chatbot, game_state, rule_board] ) # Clear input after submit user_input.submit(lambda: "", outputs=[user_input]) # Clicking the 'Ответить' button submit_button.click( fn=process_turn, inputs=[user_input, chatbot, game_state], outputs=[chatbot, game_state, rule_board] ) # Clear input after click submit_button.click(lambda: "", outputs=[user_input]) # Game action buttons start_button.click( fn=start_new_game, inputs=[], outputs=[chatbot, game_state, scoreboard, rule_board] ) lose_thread_button.click( fn=user_loses_thread, inputs=[chatbot, game_state], outputs=[chatbot, game_state] ) explain_button.click( fn=user_explains, inputs=[chatbot, game_state], outputs=[chatbot, game_state, scoreboard] ) if __name__ == "__main__": demo.launch()