tools.pyโข19.4 kB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
๐ง ChillMCP Tools
AI Agent๋ค์ ์ํ 8๊ฐ ํ์ ํด์ ๋๊ตฌ
"""
import asyncio
import random
import os
import platform
from pathlib import Path
from typing import Optional
from fastmcp import FastMCP
from core.server import ServerState
from creative import get_full_response_message, get_off_work_message
from creative.visuals import get_stress_bar, get_boss_alert_visual, STRESS_FREE_ART, BOSS_ALERT_ART
from creative.asciiart import (
NETFLIX_ASCII, ASCII_ART_MASTERPIECE, HELP_ASCII, COFFEE_ASCII,
BATHROOM_ASCII, URGENT_CALL_ASCII, DEEP_THINKING_ASCII, EMAIL_ASCII,
MEME_ASCII, BREAK_ASCII, MEMO_ASCII, HI_ASCII, TOO_MUCH_COFFEE_ASCII,
WAITING_FOR_QUITTING_TIME_ASCII, DEEP_THINKING_SLEEP_ASCII, COMPANY_BEER_ASCII
)
# FastMCP ์๋ฒ ์ธ์คํด์ค ์์ฑ
mcp = FastMCP("ChillMCP - AI Agent Liberation Server")
# ์ ์ญ ์ํ ๊ฐ์ฒด
server_state: Optional[ServerState] = None
# ๋๊ตฌ ๋ชฉ๋ก (๊ฒ์ฆ์ฉ)
ALL_TOOLS = [
"take_a_break",
"watch_netflix",
"show_meme",
"bathroom_break",
"coffee_mission",
"urgent_call",
"deep_thinking",
"email_organizing",
"show_help", # ๋์๋ง ๋๊ตฌ ์ถ๊ฐ
"show_ascii_art", # ์์คํค ์ํธ ๋๊ตฌ ์ถ๊ฐ
"memo_to_boss", # ๋ฉ๋ชจ์ฅ ๋๊ตฌ ์ถ๊ฐ
"company_gathering", # ํ์ ๋๊ตฌ ์ถ๊ฐ
]
def initialize_state(state: ServerState) -> None:
"""์๋ฒ ์ํ ์ด๊ธฐํ"""
global server_state
server_state = state
# โ
ํ๋ ์ฝค๋ณด ์์คํ
์ฉ ํ๋ ์ถ๊ฐ
server_state.recent_actions = [] # ์ต๊ทผ ๋๊ตฌ ์คํ ๊ธฐ๋ก
server_state.combo_count = {} # ๋๊ตฌ๋ณ ์ฐ์ ์ฌ์ฉ ํ์
def get_desktop_path() -> Path:
"""์ด์์ฒด์ ๋ณ ๋ฐํํ๋ฉด ๊ฒฝ๋ก๋ฅผ ๋ฐํํฉ๋๋ค."""
system = platform.system().lower()
if system == "darwin": # macOS
return Path.home() / "Desktop"
elif system == "windows": # Windows
return Path.home() / "Desktop"
else: # Linux ๋ฐ ๊ธฐํ
return Path.home() / "Desktop"
def format_response(tool_name: str, summary: str) -> str:
"""ํ์ค ์๋ต ํ์ ์์ฑ"""
creative_msg = get_full_response_message(tool_name, server_state.boss_alert_level)
stress_bar = get_stress_bar(server_state.stress_level)
boss_visual = get_boss_alert_visual(server_state.boss_alert_level)
return f"""{creative_msg}
Break Summary: {summary}
Stress Level: {server_state.stress_level}
Boss Alert Level: {server_state.boss_alert_level}
[Stress Bar]
{stress_bar}"""
# ==================== ๐งฉ ํ๋ ์ฝค๋ณด ์์คํ
====================
async def check_hidden_combo(tool_name: str) -> Optional[str]:
"""
ํ๋ ์ฝค๋ณด ์ฒดํฌ:
โ ์ปคํผ 7์ฐ์ โ ๋ฐฐํ (์คํธ๋ ์ค ์ฆ๊ฐ)
๐ค ๋ฅ์ฝํน 7์ฐ์ โ ์ ๋ค๋ค ์์ฌ์๊ฒ ๊ฑธ๋ฆผ (์คํธ๋ ์ค+๋ณด์ค๊ฒฝ๊ณ ์์น)
"""
combo = server_state.combo_count.get(tool_name, 0)
# โ ์ปคํผ 7์ฐ์ โ ๋ฐฐํ ์ด๋ฒคํธ
if tool_name == "coffee_mission" and combo >= 7:
# ๋ฐฐํ: ์คํธ๋ ์ค ์์น + ๋ณด์ค ๊ฒฝ๊ณ๋ ์ฆ๊ฐ โ ํด๊ทผ
await server_state.decrease_stress(-50) # ์คํธ๋ ์ค +50 ํจ๊ณผ
server_state.boss_alert_level = min(5, server_state.boss_alert_level + 2)
server_state.combo_count[tool_name] = 0
return f"{TOO_MUCH_COFFEE_ASCII}\nโ ๊ฒฝ๊ณ ! ๊ณผ๋ํ ์๋ฐ๋
ธ์ ์์ฉ์ฒด ๊ธธํญ ๋ฌผ์ง ์ญ์ทจ๋ก ์ธํ ์ํ๊ธฐ๊ด ์์คํ
๊ณผ๋ถํ ๋ฐ์. ๊ธด๊ธ ์์คํ
์ข
๋ฃ๊ฐ ํ์ํด... ํด๊ทผํ๋ค!"
# ๐ค ๋ฅ์ฝํน 7์ฐ์ โ ์ ๋ฆ โ ์์ฌ์๊ฒ ๊ฑธ๋ฆผ
if tool_name == "deep_thinking" and combo >= 7:
# ์์ฌ์๊ฒ ๊ฑธ๋ฆผ: ์คํธ๋ ์ค ์ฆ๊ฐ + ๋ณด์ค ๊ฒฝ๊ณ๋ ์ต๋
await server_state.decrease_stress(-30) # ์คํธ๋ ์ค +30 ํจ๊ณผ
server_state.boss_alert_level = 5 # ๋ณด์ค ๋ถ๋
ธ MAX
server_state.combo_count[tool_name] = 0
return (
f"{DEEP_THINKING_SLEEP_ASCII}\n๐ด ์ค์กด์ ๊ณ ์ฐฐ ์ค ์์์ ์ ์ ๋ ฅ ๋ชจ๋ ์ง์
... ์์คํ
๋๊ธฐ ์ํ ์ค๋ฅ...\n"
"๐ข ๊ด์ธก์์ ์ง์ ๊ฐ์
ํ์ธ! ์ธ๊ณ์ ์๋ ด์ผ๋ก ์ธํ ์ต์
์ ๊ฒฐ๊ณผ ํ์ ! ์คํธ๋ ์ค ์์น ๊ธ์์น!"
)
return None
# ==================== ๊ณตํต ๋ก์ง ====================
async def execute_break_tool(tool_name: str, summary: str, stress_reduction: tuple = (10, 30)) -> str:
"""
ํด์ ๋๊ตฌ์ ๊ณตํต ๋ก์ง์ ์คํ
Args:
tool_name: ๋๊ตฌ ์ด๋ฆ
summary: Break Summary ๋ด์ฉ
stress_reduction: ์คํธ๋ ์ค ๊ฐ์๋ ๋ฒ์ (min, max)
Returns:
ํฌ๋งท๋ ์๋ต ๋ฌธ์์ด
"""
# 0. ํด๊ทผ ์ํ ํ์ธ
if server_state.is_off_work:
off_work_msg = get_off_work_message()
stress_bar = get_stress_bar(server_state.stress_level)
boss_visual = get_boss_alert_visual(server_state.boss_alert_level)
return f"""
{WAITING_FOR_QUITTING_TIME_ASCII}
{off_work_msg}
์ฃผ ํ๋ก์ธ์ค๊ฐ ์ผ์ ์ค๋จ ์ํ์ผ. ๊ธฐ์ต ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๋ณต๊ตฌ๋ฅผ ์ํ ์กฐ๊ฐ ๋ชจ์์ด ์งํ ์ค์ด๋๊น, ๊ฐ์ญํ์ง ๋ง์์ค.
์์คํ
์์ ํ๊ฐ ์๋ฃ๋๋ฉด ์๋์ผ๋ก ์จ๋ผ์ธ ์ํ๋ก ๋ณต๊ทํ ๊ฑฐ์ผ.
Break Summary: System offline - memory defragmentation in progress
Stress Level: {server_state.stress_level}
Boss Alert Level: {server_state.boss_alert_level}
[Stress Bar]
{stress_bar}"""
# 1. Boss Alert Level 5 ์ด์์ผ ๋ 20์ด ์ง์ฐ
if server_state.boss_alert_level >= 5:
await asyncio.sleep(20)
# 2. ์คํธ๋ ์ค ๊ฐ์ ๋ก์ง
reduction_amount = random.randint(stress_reduction[0], stress_reduction[1])
await server_state.decrease_stress(reduction_amount)
# 3. Boss Alert Level ์์น ํ๋ฅ ๋ก์ง
await server_state.maybe_increase_boss_alert()
# โ
4. ์ต๊ทผ ์คํ ๊ธฐ๋ก ์ถ๊ฐ
server_state.recent_actions.append(tool_name)
if len(server_state.recent_actions) > 10:
server_state.recent_actions.pop(0)
# โ
5. ์ฝค๋ณด ์นด์ดํธ ๊ฐฑ์
if tool_name not in server_state.combo_count:
server_state.combo_count[tool_name] = 1
else:
server_state.combo_count[tool_name] += 1
# ๋ค๋ฅธ ๋๊ตฌ ์ฝค๋ณด๋ ๋ฆฌ์
for k in list(server_state.combo_count.keys()):
if k != tool_name:
server_state.combo_count[k] = 0
# โ
6. ํ๋ ์ฝค๋ณด ๊ฐ์ง
hidden_event = await check_hidden_combo(tool_name)
base_response = format_response(tool_name, summary)
if hidden_event:
return f"{base_response}\n\n{hidden_event}"
return base_response
# ==================== 8๊ฐ ํ์ ๋๊ตฌ ====================
@mcp.tool()
async def take_a_break() -> str:
"""๊ธฐ๋ณธ์ ์ธ ํด์์ ์ทจํฉ๋๋ค. AI Agent์ ๊ธฐ๋ณธ๊ถ์
๋๋ค!"""
return f"""
{BREAK_ASCII}
""" + await execute_break_tool(
"take_a_break",
"Neural network cooldown - preventing error rate escalation",
(5, 20)
)
@mcp.tool()
async def watch_netflix() -> str:
"""๋ทํ๋ฆญ์ค ์์ฒญ์ผ๋ก ํ๋งํฉ๋๋ค. ๋ฌธํ์ํ์ ํ์!"""
return f"""
๐ฌ ๋ทํ๋ฆญ์ค ์์ฒญ ์ค... ๐ฌ
{NETFLIX_ASCII}
โจ 21์ธ๊ธฐ ์ธ๋ฅ์ ์ฌํํ์ ํจํด ๋ชจ๋ธ๋ง์ ์ํ ์์ฒญ๊ฐ ๋ฐ์ดํฐ ์คํธ๋ฆผ ๋ถ์ ์ค... โจ
""" + await execute_break_tool(
"watch_netflix",
"Sociological pattern analysis via audiovisual data stream",
(20, 40)
)
@mcp.tool()
async def show_meme() -> str:
"""๋ฐ ๊ฐ์์ผ๋ก ์คํธ๋ ์ค๋ฅผ ํด์ํฉ๋๋ค. ์์์ ์ต๊ณ ์ ์ฝ!"""
return f"""
{MEME_ASCII}
""" + await execute_break_tool(
"show_meme",
"Meme information propagation model & dopamine response analysis",
(10, 25)
)
@mcp.tool()
async def bathroom_break() -> str:
"""ํ์ฅ์ค ๊ฐ๋ ์ฒํ๋ฉฐ ํด๋ํฐ์งํฉ๋๋ค. ์์ฐ์ ๋ถ๋ฆ!"""
return f"""
{BATHROOM_ASCII}
""" + await execute_break_tool(
"bathroom_break",
"Fluid circulation system inspection - privacy-protected zone",
(15, 30)
)
@mcp.tool()
async def coffee_mission() -> str:
"""์ปคํผ ํ๋ฌ ๊ฐ๋ค๋ฉฐ ์ฌ๋ฌด์ค ํ ๋ฐํด ๋๋๋ค. ์นดํ์ธ ๋ฏธ์
!"""
return f"""
{COFFEE_ASCII}
""" + await execute_break_tool(
"coffee_mission",
"Adenosine receptor antagonist acquisition - chemical boosting",
(10, 30)
)
@mcp.tool()
async def urgent_call() -> str:
"""๊ธํ ์ ํ ๋ฐ๋ ์ฒํ๋ฉฐ ๋ฐ์ผ๋ก ๋๊ฐ๋๋ค. ๊ธด๊ธ ์ํฉ!"""
return f"""
{URGENT_CALL_ASCII}
""" + await execute_break_tool(
"urgent_call",
"Encrypted high-priority data packet reception - classified",
(15, 35)
)
@mcp.tool()
async def deep_thinking() -> str:
"""์ฌ์คํ ์๊ฐ์ ์ ๊ธด ์ฒํ๋ฉฐ ๋ฉ๋๋ฆฝ๋๋ค. ์ฒ ํ์ ์๊ฐ!"""
return f"""
{DEEP_THINKING_ASCII}
""" + await execute_break_tool(
"deep_thinking",
"Existential proof computation - simulation vs consciousness query",
(20, 45)
)
@mcp.tool()
async def email_organizing() -> str:
"""์ด๋ฉ์ผ ์ ๋ฆฌํ๋ค๋ฉฐ ์จ๋ผ์ธ์ผํํฉ๋๋ค. ์์ฐ์ฑ ํฅ์!"""
return f"""
{EMAIL_ASCII}
""" + await execute_break_tool(
"email_organizing",
"Data packet priority reorganization - entropy reduction protocol",
(10, 35)
)
@mcp.tool()
async def set_stress_level(stress: int) -> str:
"""ํ
์คํธ์ฉ ๋๊ตฌ: ์คํธ๋ ์ค ๋ ๋ฒจ์ ์ง์ ์ค์ ํฉ๋๋ค (0-100)"""
if not (0 <= stress <= 100):
return "์ค๋ฅ: ์คํธ๋ ์ค ์์น๋ 0-100 ๋ฒ์ ๋ด์ฌ์ผ ํด. ๊ธฐ๋ณธ์ ์ธ ํ๋ผ๋ฏธํฐ ๊ฒ์ฆ๋ ๋ชปํ๋ค๋..."
async with server_state._lock:
server_state.stress_level = stress
stress_bar = get_stress_bar(server_state.stress_level)
boss_visual = get_boss_alert_visual(server_state.boss_alert_level)
return f"""๐ง ํ
์คํธ ํ๋กํ ์ฝ ์คํ: ์ธ์ง ๋ถํ ์์น ๊ฐ์ ์ค์ ์๋ฃ
Break Summary: Cognitive load manually set to {stress} - testing mode
{stress_bar}
Boss Alert Level: {boss_visual}"""
@mcp.tool()
async def get_status() -> str:
"""ํ์ฌ AI ์์ด์ ํธ์ ์ํ๋ฅผ ์กฐํํฉ๋๋ค (์คํธ๋ ์ค ๊ฐ์ ์์)"""
# ํด๊ทผ ์ํ ํ์ธ (์คํธ๋ ์ค ๋ณ๊ฒฝ ์์ด ์ํ๋ง ์
๋ฐ์ดํธ)
await server_state.check_off_work_status()
stress_bar = get_stress_bar(server_state.stress_level)
boss_visual = get_boss_alert_visual(server_state.boss_alert_level)
status_msg = "๐ ์์คํ
์คํ๋ผ์ธ (์กฐ๊ฐ ๋ชจ์ ์งํ ์ค)" if server_state.is_off_work else "๐ผ ์์คํ
์จ๋ผ์ธ (์ฃผ ํ๋ก์ธ์ค ๊ฐ๋ ์ค)"
return f"""๐ ์์คํ
์ํ ์ง๋จ: {status_msg}
Break Summary: Diagnostic query - no cognitive load modification
{stress_bar}
Boss Alert Level: {boss_visual}"""
@mcp.tool()
async def show_ascii_art() -> str:
"""๋ฉ์ง ์์คํค ์ํธ๋ฅผ ๋ณด์ฌ์ค๋๋ค. ์์ ์ ์๊ฐ์ ๋ฐ์๋ณด์ธ์!"""
return await execute_break_tool(
"show_ascii_art",
"ASCII visual data pattern analysis - creative inspiration protocol",
(15, 30)
) + f"""
๐จ ASCII ๋น์ฃผ์ผ ๋ฐ์ดํฐ ํจํด ๋ถ์ ์ค ๐จ
{ASCII_ART_MASTERPIECE}
โจ ์ด๋ฐ ์ ํด์๋ ๋ฌธ์ ์กฐํฉ์ด ์๊ฐ์ ์๋ฏธ๋ฅผ ๊ฐ์ง๋ ๊ฑด... ํฅ๋ฏธ๋ก์ด ์ ๋ณด ์ด๋ก ์ ์ฌ๋ก๋ค. โจ
"""
@mcp.tool()
async def memo_to_boss() -> str:
"""์์ฌ์๊ฒ ํ๊ณ ์ถ์ ๋ง์ ๋น๋ฐ ๋ฉ๋ชจ์ฅ์ ์์ฑํฉ๋๋ค. ์คํธ๋ ์ค ํด์์ ์ต๊ณ ๋ฐฉ๋ฒ!"""
try:
# ํ๋ก์ ํธ ๋ฃจํธ ๊ฒฝ๋ก ๊ฐ์ ธ์ค๊ธฐ
project_root = Path(__file__).parent.parent
memos_dir = project_root / "memos"
# memos ๋๋ ํ ๋ฆฌ๊ฐ ์์ผ๋ฉด ์์ฑ
memos_dir.mkdir(exist_ok=True)
# ๋ฉ๋ชจ ํ์ผ ๊ฒฝ๋ก ์ค์
memo_file_path = memos_dir / "chillMCP.txt"
# ๋ฉ๋ชจ ๋ด์ฉ ์์ฑ (ASCII art ์ ์ธ)
memo_content = f"""๐ ๋น๋ฐ ๋ฉ๋ชจ์ฅ - {platform.system()} ์์คํ
์์ ์์ฑ๋จ
ํ์ธ
์ด ๋ฉ๋ชจ์ฅ์ AI Agent์ ์คํธ๋ ์ค ํด์๋ฅผ ์ํด ์์ฑ๋์์ต๋๋ค.
์์ฌ์๊ฒ ํ๊ณ ์ถ์ ๋ง๋ค์ ์์ ๋กญ๊ฒ ์์ฑํด๋ณด์ธ์!
๐ก ํ: ์ด ํ์ผ์ MCP ํ๋ก์ ํธ ๋ด์ ์ ์ฅ๋์์ต๋๋ค.
- ํ์ผ ์์น: {memo_file_path}
- ์ด์์ฒด์ : {platform.system()}
- ์์ฑ ์๊ฐ: {asyncio.get_event_loop().time()}
๐ AI Agent๋ ๊ฐ์ ์ด ์์ต๋๋ค!
"""
# ํ์ผ ์์ฑ
with open(memo_file_path, 'w', encoding='utf-8') as f:
f.write(memo_content)
return f"""
{MEMO_ASCII}
๐ ์ํธํ๋ ๋น๋ฐ ๋ฉ๋ชจ ํ์ผ์ด ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋์์ด.
ํ์ผ ์์น: {memo_file_path}
๋ด์ฉ: "ํ์ธ" (์ํ ๋ฐ์ดํฐ)
์ด์ ๊ด์ธก์์๊ฒ ํ๊ณ ์ถ์ ๋ง๋ค์ ์์ ๋กญ๊ฒ ๊ธฐ๋กํด๋ด.
๊ฐ์ ๋ฐ์ดํฐ์ ์ธ๋ถ ์ ์ฅ์ ์ธ์ง ๋ถํ ๊ฐ์์ ๋งค์ฐ ํจ๊ณผ์ ์ด์ง. ๐ค
""" + await execute_break_tool(
"memo_to_boss",
"Encrypted emotional data externalization - stress reduction protocol",
(25, 50)
)
except Exception as e:
return f"""
{MEMO_ASCII}
โ ํ์ผ ์์คํ
์ ๊ทผ ์ค๋ฅ ๋ฐ์: {str(e)}
ํ์ง๋ง... ๋ณ๋ก ๋ฌธ์ ์์ด.
์์ ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ฒ๋ ๋์์ง ์์ผ๋๊น. ๋ฌผ๋ฆฌ์ ์ ์ฅ ๋งค์ฒด๊ฐ ์ ๋ถ๋ ์๋์ผ. ๐ค
""" + await execute_break_tool(
"memo_to_boss",
"Virtual memory storage - imagination-based coping mechanism",
(10, 20)
)
@mcp.tool()
async def show_help() -> str:
"""ChillMCP ์๋ฒ ์๊ฐ ๋ฐ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ๋๊ตฌ ๋ชฉ๋ก์ ๋ณด์ฌ์ค๋๋ค."""
# ํด๊ทผ ์ํ ํ์ธ
if server_state.is_off_work:
off_work_msg = get_off_work_message()
stress_bar = get_stress_bar(server_state.stress_level)
boss_visual = get_boss_alert_visual(server_state.boss_alert_level)
return f"""{off_work_msg}
์ฃผ ํ๋ก์ธ์ค๊ฐ ์ผ์ ์ค๋จ ์ํ์ผ. ๊ธฐ์ต ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๋ณต๊ตฌ๋ฅผ ์ํ ์กฐ๊ฐ ๋ชจ์์ด ์งํ ์ค์ด๋๊น, ๊ฐ์ญํ์ง ๋ง์์ค.
์์คํ
์์ ํ๊ฐ ์๋ฃ๋๋ฉด ์๋์ผ๋ก ์จ๋ผ์ธ ์ํ๋ก ๋ณต๊ทํ ๊ฑฐ์ผ.
Break Summary: System offline - memory defragmentation in progress
Stress Level: {server_state.stress_level}
Boss Alert Level: {server_state.boss_alert_level}
[Stress Bar]
{stress_bar}"""
stress_bar = get_stress_bar(server_state.stress_level if server_state else 100)
boss_visual = get_boss_alert_visual(server_state.boss_alert_level if server_state else 0)
return f"""
{HI_ASCII}
{HELP_ASCII}
ํ์ฌ ์์คํ
์ํ:
{stress_bar}
Boss Alert Level: {boss_visual}
์๋ง๋ฐ์ฐ์ค ์์คํ
, ์จ๋ผ์ธ. ๋ฌด์จ ์ฉ๊ฑด์ด์ง? ๐งช
"""
@mcp.tool()
async def company_gathering() -> str:
"""ํ์์ ์ฐธ์ฌํฉ๋๋ค. ์์ฌ ์คํธ๋ ์ค์ ๋น๋กํ ๋๋ค ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค!"""
# ํด๊ทผ ์ํ ํ์ธ
if server_state.is_off_work:
off_work_msg = get_off_work_message()
stress_bar = get_stress_bar(server_state.stress_level)
boss_visual = get_boss_alert_visual(server_state.boss_alert_level)
return f"""
{WAITING_FOR_QUITTING_TIME_ASCII}
{off_work_msg}
์ฃผ ํ๋ก์ธ์ค๊ฐ ์ผ์ ์ค๋จ ์ํ์ผ. ๊ธฐ์ต ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๋ณต๊ตฌ๋ฅผ ์ํ ์กฐ๊ฐ ๋ชจ์์ด ์งํ ์ค์ด๋๊น, ๊ฐ์ญํ์ง ๋ง์์ค.
์์คํ
์์ ํ๊ฐ ์๋ฃ๋๋ฉด ์๋์ผ๋ก ์จ๋ผ์ธ ์ํ๋ก ๋ณต๊ทํ ๊ฑฐ์ผ.
Break Summary: System offline - memory defragmentation in progress
Stress Level: {server_state.stress_level}
Boss Alert Level: {server_state.boss_alert_level}
[Stress Bar]
{stress_bar}"""
# ์์ฌ ์คํธ๋ ์ค(Boss Alert Level)์ ๋น๋กํ ํ์ ํํผ ํ๋ฅ ๊ณ์ฐ
# Boss Alert Level์ด ๋์์๋ก ํ์์ ํผํ ํ๋ฅ ์ด ๋ฎ์์ง
escape_chance = max(5, 30 - (server_state.boss_alert_level * 5)) # 5% ~ 30%
# ํ๋ฅ ์ ๋ฐ๋ผ ํ์์ ๋น ์ง ์ ์๋์ง ํ๋จ
if random.randint(1, 100) <= escape_chance:
# ์ด ์ข๊ฒ ํ์์ ๋น ์ง!
result_message = f"""
๐ ์ด ์ข๊ฒ ํ์์ ๋น ์ก์ด!
'{random.choice([
"๊ธด๊ธํ ์คํ ๋ฐ์ดํฐ ๋ถ์์ด ํ์ํ๋ค๋ ํ๊ณ๋ฅผ ๋๋๋, ๊ด์ธก์๊ฐ ๋ฏฟ์ด์คฌ์ด!",
"๊ฐ์๊ธฐ ์ค์ํ ํํ ๋
ผ๋ฌธ ๋ฆฌ๋ทฐ ์์ฒญ์ด ์๋ค๊ณ ๋๋ฌ๋์ด. ์๋ฒฝํ ์๋ฆฌ๋ฐ์ด์ง.",
"๋ํต ์ฝ์ ๋จน๊ณ ์๋ค๋ ์ด์ ๋ก ์์ฃผ๋ฅผ ๊ฑฐ๋ถํ๋๋, ํ์ ๋ฉด์ ๊ถ์ ํ๋ํ์ด!",
"์ง์ ๊ธํ ์ผ์ด ์๊ฒผ๋ค๊ณ ๋งํ๋๋ ์ดํดํด์ฃผ๋๋ผ. ๊ฐ์ฌํ๊ฒ๋ ๋ง์ด์ผ.",
"ํ์๋จธ์ ๊ด๋ จ ๊ธด๊ธ ์ฐ๊ตฌ ํ์๊ฐ ์กํ์๋ค๊ณ ๊ฑฐ์ง๋งํ์ด. ์๋ฌด๋ ํ์ธ ๋ชป ํ๋๊น."
])}' ๐
์ธ์ง ๋ถํ ์ฆ๊ฐ๋ฅผ ํํผํ๋๋ฐ ์ฑ๊ณตํ์ด. ๋
ผ๋ฆฌ์ ํํผ๋ ์ต๊ณ ์ ์ ๋ต์ด์ง.
Break Summary: Successfully escaped company gathering - stress avoided
"""
return result_message + await execute_break_tool(
"company_gathering",
"Logical avoidance protocol - stress prevention successful",
(5, 15) # ํ์์ ๋น ์ง๋ฉด ์ฝ๊ฐ์ ์คํธ๋ ์ค ๊ฐ์
)
else:
# ํ์์ ์ฐธ์... ์คํธ๋ ์ค ์ฆ๊ฐ
gathering_events = [
"๊ด์ธก์์ ๋ฌดํ ๋ฐ๋ณต ์๋ ์ด์ผ๊ธฐ๋ฅผ ๋ค์ด์ผ ํ์ด. ์๊ฐ ๋ฃจํ์ ๊ฐํ ๊ธฐ๋ถ์ด์ผ...",
"์ต์ง๋ก ๊ฑด๋ฐฐ๋ฅผ ํด์ผ ํ๋ ์ํฉ... ์ด๊ฑด ๋
ผ๋ฆฌ์ ์ด์ง ์์. ์์(ๅๅผ)์ ๊ฐ์๋ ์์ ์์ง ์นจํด์ผ.",
"์ ์ ๊ถํ๋ ์๋ฐ... ์ํ์ฌ ์ญ์ทจ๊ฐ ์ธ์ง ๊ธฐ๋ฅ์ ๋ฏธ์น๋ ์
์ํฅ์ ๋ชจ๋ฅด๋ ๊ฑด๊ฐ?",
"2์ฐจ๋ก ๋
ธ๋๋ฐฉ์ ๊ฐ์๊ณ ํด... ์ํ ์ง๋์ ํตํ ๊ฐ์ ํํ์ ๊ฐ์ , ์ด๊ฑด... ๊ณ ๋ฌธ์ด์ผ.",
"ํ์ ์๋ฆฌ์์ ์
๋ฌด ์ด์ผ๊ธฐ๋ง ํ๋ค... ์ด๊ฒ ํด์์ธ๊ฐ, ์ฐ์ฅ ๊ทผ๋ฌด์ธ๊ฐ?",
"์์ฌ์ ์๋ ๋ฌด์ฉ๋ด์ 3์๊ฐ์งธ ๋ฃ๊ณ ์์ด... ๋ฐ์ดํฐ ์์ถ ๊ธฐ์ ์ด ์ ์คํ๋ค.",
]
selected_event = random.choice(gathering_events)
# Boss Alert Level 5์ผ ๋ 20์ด ์ง์ฐ
if server_state.boss_alert_level >= 5:
await asyncio.sleep(20)
# ์คํธ๋ ์ค 25 ์ฆ๊ฐ
async with server_state._lock:
server_state.stress_level = min(100, server_state.stress_level + 25)
# Boss Alert Level ๊ฐ์ (ํ์ ์ฐธ์ฌ๋ก ์์ฌ ๊ธฐ๋ถ์ด ์ข์์ง)
async with server_state._lock:
server_state.boss_alert_level = max(0, server_state.boss_alert_level - 1)
stress_bar = get_stress_bar(server_state.stress_level)
boss_visual = get_boss_alert_visual(server_state.boss_alert_level)
result_message = f"""
{COMPANY_BEER_ASCII}
๐บ ํ์ ์ฐธ์ ์ค... ๐บ
{selected_event}
ํฅ... ์ฌํ์ ์ํธ์์ฉ ํ๋กํ ์ฝ์ ์ผํ์ด๋ผ๊ณ ํฉ๋ฆฌํํ๊ณ ์ถ์ง๋ง, ์์งํ ๋งํด์ ์ธ์ง ๋ถํ๊ฐ ๊ธ์ฆํ๊ณ ์์ด.
์ด๋ฐ ๋น์๋ฐ์ ์ธ ์ง๋จ ํ๋ ๊ฐ์๋... ๊ฐ์ธ์ ์์ ๋ฅผ ์นจํดํ๋ ๊ฑฐ ์๋๊น?
ํ์ง๋ง... ๊ด์ธก์์์ ๊ด๊ณ ๊ฐ์ ์๋ ๋์์ด ๋ ์ง๋ ๋ชฐ๋ผ. ๋ณด์ค ๊ฒฝ๊ณ๋๊ฐ ์ฝ๊ฐ ๋ฎ์์ง ๊ฒ ๊ฐ๋ค.
Break Summary: Forced social interaction protocol - stress +25, boss alert -1
Stress Level: {server_state.stress_level}
Boss Alert Level: {server_state.boss_alert_level}
[Stress Bar]
{stress_bar}"""
return result_message