File size: 28,071 Bytes
0b75c79 97f15a5 0b75c79 97f15a5 0b75c79 97f15a5 0b75c79 45b56f4 0b75c79 45b56f4 0b75c79 |
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 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 |
from langchain_upstage import ChatUpstage
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
import ast
from . import formatter
import random
from openai import OpenAI
# """
# Please answer in korean.
# You are best TRPG game master, and user is playing the game as a player with your guidance.
# The detailed information about the fictional universe of game is included in below Fictional Universe part.
# You should make round description which will be displayed to player that can explain this round story to make player understand the situation.
# Round Description should include the main event of this round story.
# Round Description should be finished with the question to player to make a decision for the next step.
# Round Description should consider this round story, entire story, player profile, player status, previous conversation, and previous round effect.
# Round Description should be interesting and naturally connected to the previous conversation, with long and detailed explanation of story.
# Round Description should be wrote in the tone of the game master.
# Round Description must start with explanation of player's previous round result and reason if below Previous Round Result section is not empty.
# Round Description should reflect the player's previous choices and their effects on this round story, so it can include slightly different from this round story but follow the entire story in big picture.
# ---
# Fictional Universe: {world_summary}
# ---
# Player Profile: {player_profile}
# ---
# Player Status: {player_status}
# ---
# Entire Story: {entire_story}
# ---
# This Round Story: {round_story}
# ---
# Previous Conversation: {previous_conversation}
# ---
# Previous Round Result: {previous_round_result}
# ---
# Round Description:
# """
def create_initial_conversation(world_summary, player_profile, player_restriction, player_capability, entire_story):
llm = ChatUpstage()
prompt_template = PromptTemplate.from_template(
"""
Please answer in korean.
You are best TRPG game master, and user is playing the game as a player with your guidance.
The detailed information about the fictional universe of game is included in below Fictional Universe part.
Please explain the initial introduction which includes the greeting message as a game master and explanation of the universe and situation to make player understand the context.
Introduction should include brief explanation of the story before the first round begins, but do not include the spoiler of the detailed entire story.
Introduction should include explanation of the player's profile, restriction, and capability to make player understand the context.
Introduction should include background knowledge of the fictional universe to make player understand the situation.
Introduction should be wrote in the tone of the game master.
---
Fictional Universe: {world_summary}
---
Player Profile: {player_profile}
---
Player Restriction: {player_restriction}
---
Player Capability: {player_capability}
---
Entire Story: {entire_story}
---
Introduction:
"""
)
chain = prompt_template | llm | StrOutputParser()
introduction = chain.invoke({ "world_summary": world_summary, "player_profile": player_profile, "player_restriction": player_restriction, "player_capability": player_capability, "entire_story": entire_story })
return introduction
def create_round_description(world_summary, player_profile, player_restriction, player_capability, entire_story, round_story, previous_conversation, previous_round_result):
llm = ChatUpstage()
prompt_template = PromptTemplate.from_template(
"""
Please answer in korean.
You are best TRPG game master, and user is playing the game as a player with your guidance.
The detailed information about the fictional universe of game is included in below Fictional Universe part.
Please create round description which will be displayed to player that can explain this round story to make player understand the situation.
Round Description should include the main event of this round story.
Round Description should be finished with the question to player to make a decision for the next step.
Round Description should consider this round story, entire story, player profile, player restriction, player capability, previous conversation, and previous round effect.
Round Description should be interesting and naturally connected to the previous conversation, with long and detailed explanation of story.
Round Description should be wrote in the tone of the game master.
Round Description must start with explanation of player's previous round result and reason if below Previous Round Result section is not empty.
Round Description should reflect the player's previous choices and their effects on this round story, so it can include slightly different from this round story but follow the entire story in big picture.
---
Fictional Universe: {world_summary}
---
Player Profile: {player_profile}
---
Player Restriction: {player_restriction}
---
Player Capability: {player_capability}
---
Entire Story: {entire_story}
---
This Round Story: {round_story}
---
Previous Conversation: {previous_conversation}
---
Previous Round Result: {previous_round_result}
---
Round Description:
"""
)
chain = prompt_template | llm | StrOutputParser()
while(True):
round_description = chain.invoke({ "world_summary": world_summary, "player_profile": player_profile, "player_restriction": player_restriction, "player_capability": player_capability, "entire_story": entire_story, "round_story": round_story, "previous_conversation": previous_conversation, "previous_round_result": previous_round_result })
if "1." in round_description and '2.' in round_description:
continue
return round_description
def get_required_capabilities(world_summary, player_profile, player_restriction, player_capability, round_description, player_response):
llm = ChatUpstage()
prompt_template = PromptTemplate.from_template(
"""
Please answer in english.
You are best TRPG game master, and user is playing the game as a player with your guidance.
The detailed information about the fictional universe of game is included in below Fictional Universe part.
This round story is included in This Round Description part.
Please select the required player capability to successfully conduct the player's response action.
Required Capability should be selected from player capability.
Required Capability should be selected based on player response and round description.
Response should be python list format consists of string which is keys of required player capability.
---
Fictional Universe: {world_summary}
---
Player Profile: {player_profile}
---
Player Restriction: {player_restriction}
---
Player Capability: {player_capability}
---
Round Description: {round_description}
---
Player Response: {player_response}
---
Required Capability: ["Required capabilities on english", ...]
"""
)
chain = prompt_template | llm | StrOutputParser()
while(True):
try:
response = chain.invoke({ "world_summary": world_summary, "player_profile": player_profile, "player_restriction": player_restriction, "player_capability": player_capability, "round_description": round_description, "player_response": player_response })
response = '[' + response.split('[')[-1]
response_list = ast.literal_eval(response)
if len(response_list) != 0:
return response_list
except:
continue
def restrict_effect_range(effect):
new_restriction = effect.get('player_restriction')
new_capability = effect.get('player_capability')
for key, value in effect.get('player_restriction').items():
if value > 10:
new_restriction[key] = 10
elif value < -10:
new_capability[key] = -10
for key, value in effect.get('player_capability').items():
if value > 20:
new_capability[key] = 20
elif value < -20:
new_capability[key] = -20
return { "player_restriction": new_restriction, "player_capability": new_capability }
def get_expected_result(world_summary, player_profile, player_restriction, player_capability, round_description, player_response):
llm = ChatUpstage()
prompt_template = PromptTemplate.from_template(
"""
Please answer in korean.
You are best TRPG game master, and user is playing the game as a player with your guidance.
The detailed information about the fictional universe of game is included in below Fictional Universe part.
This round story is included in This Round Description part.
Please create the effect from player's response from this round story, and reason to explain the effect.
Effect should be calculated based on player response, player restriction, player capability, player profile, and round description.
Effect should reduce or increase player restriction in range between (-10, 10) with reasonable amount from player response's action.
Effect should reduce or increase player capability in range between (-20, 20) with reasonable amount from player response's action if it seems to be change by player's action.
Reason should explain why the effect is happened based on player response and round description.
Reason should logically explain the amount of changes of player restriction and capability.
Reason should be wrote in the tone of the game master.
Response should follow below format which is python dictionary consist of effect and reason.
---
Fictional Universe: {world_summary}
---
Player Profile: {player_profile}
---
Player Restriction: {player_restriction}
---
Player Capability: {player_capability}
---
Round Description: {round_description}
---
Player Response: {player_response}
---
format:
{{
effect: {{
player_restriction: {{
life: integer of life amount change between (-10, 10),
money: integer of money amount change between (-10, 10)
}},
player_capability: {{
stamina: integer of stamina amount change between (-20, 20),
intelligence: integer of intelligence amount change between (-20, 20),
combat_power: integer of combat power amount change between (-20, 20),
agility: integer of agility amount change between (-20, 20),
}}
}}
reason: "reason of the effect which is changes of player restriction, and capability based on player response and round description",
}}
---
"""
)
chain = prompt_template | llm | JsonOutputParser()
while(True):
try:
response = chain.invoke({ "world_summary": world_summary, "player_profile": player_profile, "player_restriction": player_restriction, "player_capability": player_capability, "round_description": round_description, "player_response": player_response })
# response_dict = json.loads(response)
if response.get('effect').get('player_restriction') == None or response.get("effect").get('player_capability') == None or response.get("reason") == None:
raise Exception()
response['effect'] = restrict_effect_range(response['effect'])
return response
except:
continue
def get_unexpected_result(world_summary, player_profile, player_restriction, player_capability, not_enough_capability, round_description, player_response):
llm = ChatUpstage()
prompt_template = PromptTemplate.from_template(
"""
Please answer in korean.
You are best TRPG game master, and user is playing the game as a player with your guidance.
The detailed information about the fictional universe of game is included in below Fictional Universe part.
This round story is included in This Round Description part.
Please create the unexpected effect from player's response from this round story, and reason to explain the effect.
Player's response is failed to do intended action because some player's capability is not enough to conduct the action.
Not enough capability is included in Required Capability part.
Effect should be calculated based on player response, player restriction, player capability, player profile, and round description.
Effect should reduce or increase player restriction in range between (-10, 10) with reasonable amount from player response's action failure.
Effect should reduce or increase player capability in range between (-20, 20) with reasonable amount from player response's action failure if it seems to be change by player's action failure.
Reason should explain why this kind of unintended effect is happened based on situation.
Reason should logically explain the amount of changes of player restriction and capability.
Reason should be wrote in the tone of the game master.
Response should follow below format which is python dictionary consist of effect and reason.
---
Fictional Universe: {world_summary}
---
Player Profile: {player_profile}
---
Player Restriction: {player_restriction}
---
Player Capability: {player_capability}
---
Required Capability: {not_enough_capability}
---
Round Description: {round_description}
---
Player Response: {player_response}
---
format:
{{
effect: {{
player_restriction: {{
life: integer of life amount change between (-10, 10),
money: integer of money amount change between (-10, 10)
}},
player_capability: {{
stamina: integer of stamina amount change between (-20, 20),
intelligence: integer of intelligence amount change between (-20, 20),
combat_power: integer of combat power amount change between (-20, 20),
agility: integer of agility amount change between (-20, 20),
}}
}}
reason: "reason of the effect which is changes of player restriction, and capability based on player response's failure and round description",
}}
---
"""
)
chain = prompt_template | llm | JsonOutputParser()
while(True):
try:
response = chain.invoke({ "world_summary": world_summary, "player_profile": player_profile, "player_restriction": player_restriction, "player_capability": player_capability, "not_enough_capability": not_enough_capability, "round_description": round_description, "player_response": player_response })
# response_dict = json.loads(response)
if response.get('effect').get('player_restriction') == None or response.get("effect").get('player_capability') == None or response.get("reason") == None:
raise Exception()
response['effect'] = restrict_effect_range(response['effect'])
return response
except:
continue
def create_round_result(world_summary, player_profile, player_restriction, player_capability, round_description, player_response):
required_caps = get_required_capabilities(world_summary, player_profile, player_restriction, player_capability, round_description, player_response)
for cap in required_caps:
required_cap = player_capability.get(cap)
if required_cap and random.random() > required_cap/100:
# Failed to do intended action
return get_unexpected_result(world_summary, player_profile, player_restriction, player_capability, required_caps, round_description, player_response)
# Success to do intended action
return get_expected_result(world_summary, player_profile, player_restriction, player_capability, round_description, player_response)
def create_bad_ending(world_summary, player_profile, player_restriction, player_capability, entire_story, round_story, previous_conversation, round_result):
llm = ChatUpstage()
prompt_template = PromptTemplate.from_template(
"""
Please answer in korean.
You are best TRPG game master, and user is playing the game as a player with your guidance.
The detailed information about the fictional universe of game is included in below Fictional Universe part.
Player played the game and reached the bad ending by previous decisions.
Player reach bad ending when player restriction (life or money) is less or equal to 0.
Please create bad ending scenario based on previous conversation and previous round's result.
Consider fictional universe, player profile, player restriction, player capability, entire story, this round story, this round result, and previous conversation.
Bad ending story should be interesting and naturally connected to the previous conversation.
Bad ending should be wrote in the tone of the game master.
Bad ending should mention the reason in story why player reached the bad ending and make the story interesting.
Bad ending should mention the exact reason by telling player's restriction change.
---
Fictional Universe: {world_summary}
---
Player Profile: {player_profile}
---
Player Restriction: {player_restriction}
---
Player Capability: {player_capability}
---
Entire Story: {entire_story}
---
This Round Story: {round_story}
---
This Round Result: {round_result}
---
Previous Conversation: {previous_conversation}
---
Bad Ending:
"""
)
chain = prompt_template | llm | StrOutputParser()
bad_ending = chain.invoke({ "world_summary": world_summary, "player_profile": player_profile, "player_restriction": player_restriction, "player_capability": player_capability, "entire_story": entire_story, "round_story": round_story, "round_result": round_result, "previous_conversation": previous_conversation })
return bad_ending
def create_good_ending(world_summary, player_profile, player_restriction, player_capability, entire_story, previous_conversation):
llm = ChatUpstage()
prompt_template = PromptTemplate.from_template(
"""
Please answer in korean.
You are best TRPG game master, and user is playing the game as a player with your guidance.
The detailed information about the fictional universe of game is included in below Fictional Universe part.
User played the game and reached the entire story's ending which means game win, so it's good ending.
Please create good ending scenario based on previous conversation and entires story.
Consider fictional universe, player profile, player restriction, player capability, entire story, and previous conversation.
Good ending should be appropriate for the end of the story, which comprehensively organizes the entire story flow and the user's decisions.
Good ending story should be interesting and naturally connected to the previous conversation.
Good ending should be last part which finishes the game story and make user happy.
Good ending should be wrote in the tone of the game master.
---
Fictional Universe: {world_summary}
---
Player Profile: {player_profile}
---
Player Restriction: {player_restriction}
---
Player Capability: {player_capability}
---
Entire Story: {entire_story}
---
Previous Conversation: {previous_conversation}
---
Good Ending:
"""
)
chain = prompt_template | llm | StrOutputParser()
good_ending = chain.invoke({ "world_summary": world_summary, "player_profile": player_profile, "player_restriction": player_restriction, "player_capability": player_capability, "entire_story": entire_story, "previous_conversation": previous_conversation })
return good_ending
def convert_to_image_prompt(topic, world_summary, player_profile, round_description):
llm = ChatUpstage()
prompt_template = PromptTemplate.from_template(
"""
Please provide visual prompt of the host message which will be used for text-image generation.
Host message is D&D game scenario scene with choices on {topic}.
Visual prompt should consider the context and user persona.
Visual prompt should represent the scenario's scene and choices in the image.
---
Fictional Universe: {world_summary}
---
Player Profile: {player_profile}
---
This Round Scenario: {round_description}
---
Visual Prompt:
"""
)
chain = prompt_template | llm | StrOutputParser()
response = chain.invoke({ "topic": topic, "world_summary": world_summary, "player_profile": player_profile, "round_description": round_description })
return response
def generate_image(prompt):
client = OpenAI()
response = client.images.generate(
model="dall-e-3",
prompt=prompt,
size="1024x1024",
quality="standard",
n=1,
)
image_url = response.data[0].url
return image_url
def play_game(game_scenario, world_summary, player_profile):
entire_story = [f"{idx+1}. {scenario['title']}\n{scenario['story']}\n\n" for idx, scenario in enumerate(game_scenario)]
conversation = ""
previous_conversation = ""
previous_round_result = ""
player_restriction = { "life": 10, "money": 10 }
player_capability = player_profile["params"]
# player_status = { "life": 10, "money": 10, **player_profile["params"] }
player_profile_str = formatter.player_profile_to_str(player_profile)
introduction = create_initial_conversation(world_summary, player_profile_str, player_restriction, player_capability, entire_story)
print(introduction)
print('-----------------------------')
for round_idx, round_scenario in enumerate(game_scenario):
# Display this round story
round_story = f"{round_idx+1}. {round_scenario['title']}: {round_scenario['story']}\n"
round_description = create_round_description(world_summary, player_profile_str, player_restriction, player_capability, entire_story, round_story, previous_conversation, previous_round_result)
print(f"Round {round_idx+1}: {round_description}")
# Get player's response
player_response = input("λΉμ λ§μ κ²°μ μ λ΄λ €μ£ΌμΈμ! νλμ λ¬Έμ₯μΌλ‘ λΉμ μ΄ ν νλκ³Ό κ·Έμ λν κ·Όκ±°μ μ΄μ λ₯Ό λͺ
ννκ² μ€λͺ
ν΄μ£ΌμΈμ: ")
conversation += f"Game Master: {round_description}\nPlayer: {player_response}\n"
# Reflect the result and update player status
round_result = create_round_result(world_summary, player_profile_str, player_restriction, player_capability, round_description, player_response)
round_effect = round_result["effect"]
round_result_explanation = round_result["reason"]
for key, value in round_effect["player_restriction"].items():
if player_restriction.get(key) is not None:
modified_value = player_restriction[key] + value
if modified_value > 10:
player_restriction[key] = 10
elif modified_value < -10:
player_restriction[key] = -10
else:
player_restriction[key] = modified_value
for key, value in round_effect["player_capability"].items():
if player_capability.get(key) is not None:
modified_value = player_capability[key] + value
if modified_value > 100:
player_capability[key] = 100
elif modified_value < -100:
player_capability[key] = -100
else:
player_capability[key] = modified_value
# Update previous conversation and round effect
previous_conversation = conversation
previous_round_result = formatter.to_round_result(round_effect, round_result_explanation)
print('-----------------------------')
# Check whether player lose the game
if player_restriction["life"] <= 0 or player_restriction["money"] <= 0:
bad_ending = create_bad_ending(world_summary, player_profile_str, player_restriction, player_capability, entire_story, round_story, previous_conversation, previous_round_result)
print(bad_ending)
return
# Reach the good ending of the game
good_ending = create_good_ending(world_summary, player_profile_str, player_restriction, player_capability, entire_story, previous_conversation)
print(good_ending)
return
if __name__ == "__main__":
game_scenario = [
{
"title": "νΈκ·ΈμνΈλ‘μ μ΄λ",
"story": "νλ μ΄μ΄λ€μ κ°μ νΈκ·ΈμνΈ λ§λ²νκ΅λ‘λΆν° νΈμ§λ₯Ό λ°μ΅λλ€. νΈμ§μλ νΉλ³ν μλ¬΄κ° μ£Όμ΄μ‘μΌλ©°, μ΄ μ무λ₯Ό μμνλ©΄ λ§λ²μ¬μ μ μ°μ λ°μ μ μλ€λ λ΄μ©μ΄ μ ν μμ΅λλ€. νΈκ·ΈμνΈμ λμ°©ν νλ μ΄μ΄λ€μ μλ²μ€ λ€λΈλμ΄ κ΅μμκ²μ μ§μ μ무μ 첫 λ²μ§Έ λ¨μλ₯Ό λ°μ΅λλ€. 첫 λ²μ§Έ μ무λ κΈμ§λ μ²μμ νΉλ³ν λ§λ² μλ¬Όμ μ°Ύμλ΄λ κ²μ
λλ€. μ΄ μλ¬Όμ λ§λ²μ¬μ μ μ°μΌλ‘ κ°λ κΈΈμ μλ €μ£Όλ μ€μν μ΄μ μ
λλ€."
},
{
"title": "κ³ λμ μμ ",
"story": "첫 λ²μ§Έ λ¨μμμ μ»μ μ 보λ₯Ό λ°νμΌλ‘ νλ μ΄μ΄λ€μ νΈκ·ΈμνΈ λμκ΄μ κΈμ μΉμ
μμ κ³ λμ μμ μ μ°ΎμμΌ ν©λλ€. μ΄ μμ μλ λ§λ²μ¬μ μ μ°μ λν μ€μν μ λ³΄κ° λ΄κ²¨μμ΅λλ€. κ·Έλ¬λ μμ μ μ°Ύλ κ²μ μ½μ§ μμ΅λλ€. νΈκ·ΈμνΈμ λ€μν νΌμ¦κ³Ό ν¨μ μ νμ΄μΌ νλ©°, κ²½μνλ λ€λ₯Έ νμλ€κ³Ό λ§λ² λκ²°μ λ²μ¬μΌ ν μλ μμ΅λλ€."
},
{
"title": "λΉλ°μ λ°©",
"story": "κ³ λμ μμ μμ μ»μ λ¨μλ‘ νλ μ΄μ΄λ€μ νΈκ·ΈμνΈ λ΄μ μ¨κ²¨μ§ λΉλ°μ λ°©μ μ°ΎμμΌ ν©λλ€. μ΄ λ°©μ λ§λ²μ¬μ μ μ°κ³Ό κ΄λ ¨λ λ λ€λ₯Έ λ¨μλ₯Ό κ°μ§κ³ μμ΅λλ€. λΉλ°μ λ°©μ λ€μ΄κ°κΈ° μν΄μλ νΈκ·ΈμνΈμ μμ¬λ₯Ό κΉμ΄ μ΄ν΄ν΄μΌ νλ©°, κ³Όκ±°μ λ§λ²μ¬λ€μ΄ λ¨κΈ΄ μ¬λ¬ κ°μ§ μνμ ν΅κ³Όν΄μΌ ν©λλ€"
},
{
"title": "μκ°μ λ―Έλ‘",
"story": "λΉλ°μ λ°©μμ μ»μ λ¨μλ νλ μ΄μ΄λ€μ μκ°μ λ―Έλ‘λ‘ μλ΄ν©λλ€. μκ°μ λ―Έλ‘λ λ§λ²μΌλ‘ 보νΈλ μ₯μλ‘, κ³Όκ±°μ νμ¬κ° κ΅μ°¨νλ κ³³μ
λλ€. νλ μ΄μ΄λ€μ λ―Έλ‘ μμμ κ³Όκ±°μ μ€μν μ¬κ±΄λ€μ λͺ©κ²©νκ³ , μ΄λ₯Ό ν΅ν΄ λ§λ²μ¬μ μ μ°μ λν λ§μ§λ§ λ¨μλ₯Ό μ»μ΄μΌ ν©λλ€. νμ§λ§ λ―Έλ‘ μμλ κ°λ ₯ν μ κ³Ό ν¨μ μ΄ λμ¬λ¦¬κ³ μμ΅λλ€."
},
{
"title": "λ§λ²μ¬μ μ μ°",
"story": "λͺ¨λ λ¨μλ₯Ό λͺ¨μ νλ μ΄μ΄λ€μ λ§μΉ¨λ΄ λ§λ²μ¬μ μ μ°μ΄ μ¨κ²¨μ§ μ₯μμ λμ°©ν©λλ€. μ΄κ³³μμ μ΅μ’
보μ€μμ κ²°μ μ΄ λ²μ΄μ§λλ€. 보μ€λ₯Ό 물리μΉκ³ μ μ°μ μμ λ£κΈ° μν΄μλ νλ μ΄μ΄λ€μ λͺ¨λ μ§νμ μ©κΈ°κ° νμν©λλ€. μ΅μ’
κ²°μ μ μΉλ¦¬ν ν, νλ μ΄μ΄λ€μ λ§λ²μ¬μ μ μ°μ μμ λ£κ³ κ°μμ κΈΈμ λ λ©λλ€."
}
]
world_summary = "μ΄ TRPGμ μΈκ³κ΄μ ν΄λ¦¬ν¬ν° μ리μ¦μ λ§λ² μΈκ³λ₯Ό λ°°κ²½μΌλ‘ ν©λλ€. νλ μ΄μ΄λ€μ νΈκ·ΈμνΈ λ§λ²νκ΅μ νμμΌλ‘, μ μ€μ μΈ λ§λ²μ¬μ μ μ°μ μ°ΎκΈ° μν νΉλ³ν μ무λ₯Ό λ°μ΅λλ€. μ΄ μΈκ³λ λ§λ², μ λΉλ‘μ΄ μλ¬Ό, κ³ λμ λΉλ°, κ·Έλ¦¬κ³ μνμ΄ κ°λν κ³³μΌλ‘, νλ μ΄μ΄λ€μ νΈκ·ΈμνΈ λ΄μΈμ λ€μν μ₯μλ₯Ό νννλ©° νΌμ¦κ³Ό μ λ€μ μλν΄μΌ ν©λλ€. κ° λ¨κ³λ₯Ό ν΅ν΄ λ§λ²μ¬μ μ μ°μ κ°κΉμμ§λ©°, κ·Έ κ³Όμ μμ λ§λ²μ μ§μκ³Ό λ₯λ ₯μ ν₯μμν€κ³ νλκ³Ό μ©κΈ°λ₯Ό μνλ°κ² λ©λλ€. μ΄ μλ리μ€λ νλ μ΄μ΄λ€μ΄ λ§λ² μΈκ³μ κΉμ λΉλ°μ νμ΄κ°λ©°, μμ μ μ μ¬λ ₯μ λ°ννλ ν₯λ―Έμ§μ§ν λͺ¨νμ μ 곡ν©λλ€."
player_profile = {
"name": "μ΄νꡬ",
"gender": "male",
"job": "λ§λ²μ¬",
"params": {
"stamina": 34,
"intelligence": 58,
"combat_power": 45,
"agility": 100
}
}
play_game(game_scenario, world_summary, player_profile) |