humanda5 commited on
Commit
ba4c3a1
ยท
1 Parent(s): abe9cba

error state

Browse files
npc_social_network/README.txt CHANGED
@@ -168,8 +168,8 @@ GET /run_npc_simulation
168
  | 15๋‹จ๊ณ„ | ํ–‰๋™ ๊ณ„ํš ์ƒ์„ฑ๊ธฐ (LLM Planner ์—ฐ๋™) | โœ… ์™„๋ฃŒ | Planner ์—ฐ๋™์€ ์‹œ์ž‘ ์ „
169
  | 16๋‹จ๊ณ„ | ์‚ฌํšŒ์  ํ”„๋กœํŒŒ์ผ ์‹œ์Šคํ…œ ๋„์ž… | โœ… ์™„๋ฃŒ | ๊ด€๊ณ„ ์„ค๋ช… โ†’ ์‹œ๊ฐํ™” ๊ตฌ์กฐ๋กœ ํ™•์žฅ ์˜ˆ์ •
170
  | 17๋‹จ๊ณ„ | ์ƒ์ง• ๊ธฐ์–ต / ๋Œ€ํ‘œ ๊ธฐ์–ต ์ƒ์„ฑ | โœ… ์™„๋ฃŒ | ์ƒ์ง• ๊ธฐ์–ต ๋ถ„๋ฅ˜/์š”์•ฝ ์•„์ง ๋ฏธ์‹คํ–‰
171
- | 18๋‹จ๊ณ„ | ๊ธฐ์–ต ์ฒด๊ณ„ ํ™•์žฅ: ์‹œ๊ฐ„ ๋งฅ๋ฝ ๋ถ€์—ฌ | โณ ๋ฏธ์ง„ํ–‰ | ๊ธฐ์–ต์— ์‹œ๊ฐ„ ๋งฅ๋ฝ/๊ณ„์ ˆ/์‹œ๊ธฐ ๋ถ€์—ฌ ๋ฏธ์™„๋ฃŒ
172
- | 19๋‹จ๊ณ„ | ์„ฑ๊ฒฉ ๋ณ€ํ™” ์‹œ์Šคํ…œ ์™„์„ฑ | โณ ๋ฏธ์ง„ํ–‰ | ์ค‘์š”ํ•œ ๊ธฐ์–ต(Memory)๊ณผ ๊ฐ•๋ ฌํ•œ ๊ฐ์ •(Emotion)์ด ๋ˆ„์ ๋จ์— ๋”ฐ๋ผ NPC์˜ ์„ฑ๊ฒฉ(sensitive, stoic ๋“ฑ)์ด ์ ์ง„์ ์œผ๋กœ ๋ณ€ํ™”ํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„
173
  | 20๋‹จ๊ณ„ | ์ค‘๊ฐ„ ํ…Œ์ŠคํŠธ ๋ฐ ์•ˆ์ •ํ™” | โณ ๋ฏธ์ง„ํ–‰ |
174
 
175
  # ์‚ฌํšŒ์  ์ƒํ˜ธ์ž‘์šฉ ์‹ฌํ™” (Social Interaction Deepening)
 
168
  | 15๋‹จ๊ณ„ | ํ–‰๋™ ๊ณ„ํš ์ƒ์„ฑ๊ธฐ (LLM Planner ์—ฐ๋™) | โœ… ์™„๋ฃŒ | Planner ์—ฐ๋™์€ ์‹œ์ž‘ ์ „
169
  | 16๋‹จ๊ณ„ | ์‚ฌํšŒ์  ํ”„๋กœํŒŒ์ผ ์‹œ์Šคํ…œ ๋„์ž… | โœ… ์™„๋ฃŒ | ๊ด€๊ณ„ ์„ค๋ช… โ†’ ์‹œ๊ฐํ™” ๊ตฌ์กฐ๋กœ ํ™•์žฅ ์˜ˆ์ •
170
  | 17๋‹จ๊ณ„ | ์ƒ์ง• ๊ธฐ์–ต / ๋Œ€ํ‘œ ๊ธฐ์–ต ์ƒ์„ฑ | โœ… ์™„๋ฃŒ | ์ƒ์ง• ๊ธฐ์–ต ๋ถ„๋ฅ˜/์š”์•ฝ ์•„์ง ๋ฏธ์‹คํ–‰
171
+ | 18๋‹จ๊ณ„ | ๊ธฐ์–ต ์ฒด๊ณ„ ํ™•์žฅ: ์‹œ๊ฐ„ ๋งฅ๋ฝ ๋ถ€์—ฌ | โœ… ์™„๋ฃŒ | ๊ธฐ์–ต์— ์‹œ๊ฐ„ ๋งฅ๋ฝ/๊ณ„์ ˆ/์‹œ๊ธฐ ๋ถ€์—ฌ ๋ฏธ์™„๋ฃŒ
172
+ | 19๋‹จ๊ณ„ | ์„ฑ๊ฒฉ ๋ณ€ํ™” ์‹œ์Šคํ…œ ์™„์„ฑ | โœ… ์™„๋ฃŒ | ์ค‘์š”ํ•œ ๊ธฐ์–ต(Memory)๊ณผ ๊ฐ•๋ ฌํ•œ ๊ฐ์ •(Emotion)์ด ๋ˆ„์ ๋จ์— ๋”ฐ๋ผ NPC์˜ ์„ฑ๊ฒฉ(sensitive, stoic ๋“ฑ)์ด ์ ์ง„์ ์œผ๋กœ ๋ณ€ํ™”ํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„
173
  | 20๋‹จ๊ณ„ | ์ค‘๊ฐ„ ํ…Œ์ŠคํŠธ ๋ฐ ์•ˆ์ •ํ™” | โณ ๋ฏธ์ง„ํ–‰ |
174
 
175
  # ์‚ฌํšŒ์  ์ƒํ˜ธ์ž‘์šฉ ์‹ฌํ™” (Social Interaction Deepening)
npc_social_network/maps/manager/simulation_manager.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # portfolio/npc_social_network/map/manager/simulation_manager.py
2
+ import pickle
3
+ import os
4
+ from npc_social_network.npc.npc_manager import NPCManager
5
+
6
+ SAVE_DIR = "data/saves"
7
+ if not os.path.exists(SAVE_DIR):
8
+ os.makedirs(SAVE_DIR)
9
+
10
+ def save_simulation(npc_manager: NPCManager, filename: str = "simulation_state.pkl"):
11
+ """
12
+ [NEW] ํ˜„์žฌ NPC ๋งค๋‹ˆ์ €์˜ ์ƒํƒœ๋ฅผ ํŒŒ์ผ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
13
+ """
14
+ filepath = os.path.join(SAVE_DIR, filename)
15
+ try:
16
+ with open(filepath, "wb") as f:
17
+ pickle.dump(npc_manager, f)
18
+ print(f"โœ… ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ƒํƒœ๊ฐ€ '{filepath}'์— ์„ฑ๊ณต์ ์œผ๋กœ ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
19
+ except Exception as e:
20
+ print(f"โŒ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ €์žฅ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
21
+
22
+ def load_simulation(filename: str = "simulation_state.pkl") -> NPCManager | None:
23
+ """
24
+ [NEW] ํŒŒ์ผ์—์„œ NPC ๋งค๋‹ˆ์ €์˜ ์ƒํƒœ๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
25
+ """
26
+ filepath = os.path.join(SAVE_DIR, filename)
27
+ if not os.path.exists(filepath):
28
+ print("โ„น๏ธ ์ €์žฅ๋œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ํŒŒ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.")
29
+ return None
30
+
31
+ try:
32
+ with open(filepath, "rb") as f:
33
+ npc_manager = pickle.load(f)
34
+ print(f"โœ… ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ƒํƒœ๋ฅผ '{filepath}'์—์„œ ์„ฑ๊ณต์ ์œผ๋กœ ๋ถˆ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.")
35
+ return npc_manager
36
+ except Exception as e:
37
+ print(f"โŒ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
38
+ return None
npc_social_network/maps/manager/village_map.py CHANGED
@@ -15,14 +15,14 @@ class Building:
15
  screen.blit(self.image, (self.x * tile_size, self.y * tile_size))
16
 
17
  class VillageMap:
18
- def __init__(self, image_loader, tile_size, grid_width, grid_height):
19
  self.image_loader = image_loader
20
  self.tile_size = tile_size
21
  self.grid_width = grid_width
22
  self.grid_height = grid_height
23
  self.tiles = []
24
  self.buildings = []
25
- self.npc_manager = NPCManager()
26
 
27
  def generate(self):
28
  import random
@@ -47,6 +47,13 @@ class VillageMap:
47
  elin_path = [[2,3], [3,3], [4,3], [5,3], [5,4], [5,5], [4,5], [3, 5], [2,5], [2,4]]
48
  elin = NPC("Elin", "farmer", elin_path, self.image_loader.load("npc", "default"))
49
  self.npc_manager.add_npc(elin)
 
 
 
 
 
 
 
50
 
51
  def draw(self, screen):
52
  for x, y, image in self.tiles:
 
15
  screen.blit(self.image, (self.x * tile_size, self.y * tile_size))
16
 
17
  class VillageMap:
18
+ def __init__(self, image_loader, tile_size, grid_width, grid_height, npc_manager: NPCManager):
19
  self.image_loader = image_loader
20
  self.tile_size = tile_size
21
  self.grid_width = grid_width
22
  self.grid_height = grid_height
23
  self.tiles = []
24
  self.buildings = []
25
+ self.npc_manager = npc_manager
26
 
27
  def generate(self):
28
  import random
 
47
  elin_path = [[2,3], [3,3], [4,3], [5,3], [5,4], [5,5], [4,5], [3, 5], [2,5], [2,4]]
48
  elin = NPC("Elin", "farmer", elin_path, self.image_loader.load("npc", "default"))
49
  self.npc_manager.add_npc(elin)
50
+ # ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ๋‹ค๋ฅธ NPC๋“ค๋„ ์ถ”๊ฐ€
51
+ bob = NPC("Bob", "blacksmith", [[1,1], [1,2], [2,2]], self.image_loader.load("npc", "default"))
52
+ self.npc_manager.add_npc(bob)
53
+
54
+ alice = NPC("Alice", "merchant", [[8,8], [9,8], [9,9]], self.image_loader.load("npc", "default"))
55
+ self.npc_manager.add_npc(alice)
56
+
57
 
58
  def draw(self, screen):
59
  for x, y, image in self.tiles:
npc_social_network/maps/villages/town_hall.py CHANGED
@@ -1,12 +1,15 @@
1
  # portfolio/npc_social_network/maps/villages/town_hall.py
 
 
 
 
 
 
 
 
 
2
 
3
  def run_town_hall_simulation():
4
- # ๋ฉ”์ธ ์‹คํ–‰ ํŒŒ์ผ
5
- import pygame
6
- import sys
7
- from npc_social_network.maps.manager.image_loader import ImageLoader
8
- from npc_social_network.maps.manager.village_map import VillageMap
9
- from npc_social_network.maps.engine.game_engine import GameEngine
10
 
11
  # ์ดˆ๊ธฐ ์„ค์ •
12
  pygame.init()
@@ -20,36 +23,60 @@ def run_town_hall_simulation():
20
  clock = pygame.time.Clock()
21
  font = pygame.font.SysFont("malgungothic", 20) # ํ•œ๊ธ€ ์ถœ๋ ฅ์šฉ
22
 
 
 
 
 
 
 
 
 
 
23
  # ๋กœ๋”ฉ
24
  image_loader = ImageLoader(tile_size)
25
- village = VillageMap(image_loader, tile_size, width, height)
26
  village.generate()
27
 
28
-
29
- # npc ๋ฆฌ์ŠคํŠธ ์ถ”์ถœ
30
- npcs = village.npc_manager.npcs
 
31
 
32
  # ๊ฒŒ์ž„ ์—”์ง„ ์ดˆ๊ธฐ ์„ธํŒ…
33
- engine = GameEngine(screen, font, village, ["์•„์นจ", "์ ์‹ฌ", "์ €๋…", "๋ฐค"], npcs)
34
 
35
  # pygame ๋ฃจํ”„
36
  runnig = True
37
  while runnig:
38
- screen.fill((255, 255, 255))
39
- engine.draw()
40
- pygame.display.update()
41
- clock.tick(10) # ์ดˆ๋‹น 10ํ”„๋ ˆ์ž„
42
- engine.update()
43
-
44
  for event in pygame.event.get():
45
  if event.type == pygame.QUIT:
46
- runnig = False
47
- elif event.type == pygame.MOUSEBUTTONDOWN:
48
- engine.handle_click(pygame.mouse.get_pos())
49
  elif event.type == pygame.KEYDOWN:
50
- if event.key == pygame.K_ESCAPE:
 
 
 
 
 
 
 
 
 
 
 
 
51
  engine.clear_selected_npc() # ESC๋กœ ์„ ํƒ ํ•ด์ œ
 
 
 
 
 
 
 
 
52
 
 
 
53
  pygame.quit()
54
  sys.exit()
55
 
 
1
  # portfolio/npc_social_network/maps/villages/town_hall.py
2
+ # ๋ฉ”์ธ ์‹คํ–‰ ํŒŒ์ผ
3
+ import pygame
4
+ import sys
5
+ from npc_social_network.simulation_manager import save_simulation, load_simulation
6
+ from npc_social_network.maps.manager.image_loader import ImageLoader
7
+ from npc_social_network.maps.manager.village_map import VillageMap
8
+ from npc_social_network.maps.engine.game_engine import GameEngine
9
+ from npc_social_network.npc.npc_manager import NPCManager
10
+ from npc_social_network.npc.npc_base import NPC
11
 
12
  def run_town_hall_simulation():
 
 
 
 
 
 
13
 
14
  # ์ดˆ๊ธฐ ์„ค์ •
15
  pygame.init()
 
23
  clock = pygame.time.Clock()
24
  font = pygame.font.SysFont("malgungothic", 20) # ํ•œ๊ธ€ ์ถœ๋ ฅ์šฉ
25
 
26
+ # ์ €์žฅ/๋ถˆ๋Ÿฌ์˜ค๊ธฐ
27
+ npc_manager = load_simulation() # ์ €์žฅ๋œ ์ƒํƒœ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์‹œ๋„
28
+
29
+ if npc_manager is None:
30
+ # ์ €์žฅ๋œ ํŒŒ์ผ์ด ์—†์œผ๋ฉด ์ƒˆ๋กœ ์‹œ์ž‘
31
+ npc_manager = NPCManager()
32
+ # ์—ฌ๊ธฐ์— ์ดˆ๊ธฐ NPC๋“ค์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋กœ์ง์„ ๋„ฃ์Šต๋‹ˆ๋‹ค.
33
+ # ์˜ˆ์‹œ: npc_manager.add_npc(NPC(name="์—˜๋ผ", ...))
34
+
35
  # ๋กœ๋”ฉ
36
  image_loader = ImageLoader(tile_size)
37
+ village = VillageMap(image_loader, tile_size, width, height, npc_manager)
38
  village.generate()
39
 
40
+ if len(npc_manager.all()) == 0:
41
+ # ๋ถˆ๋Ÿฌ์˜จ ๋ฐ์ดํ„ฐ๊ฐ€ ๋น„์–ด์žˆ๊ฑฐ๋‚˜, ์ƒˆ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ
42
+ village.generate()
43
+ print("์ƒˆ๋กœ์šด NPC๋“ค์„ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.")
44
 
45
  # ๊ฒŒ์ž„ ์—”์ง„ ์ดˆ๊ธฐ ์„ธํŒ…
46
+ engine = GameEngine(screen, font, village, ["์•„์นจ", "์ ์‹ฌ", "์ €๋…", "๋ฐค"], npc_manager)
47
 
48
  # pygame ๋ฃจํ”„
49
  runnig = True
50
  while runnig:
 
 
 
 
 
 
51
  for event in pygame.event.get():
52
  if event.type == pygame.QUIT:
53
+ running = False
 
 
54
  elif event.type == pygame.KEYDOWN:
55
+ if event.key == pygame.K_s: # 'S' ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ์ €์žฅ
56
+ save_simulation(npc_manager)
57
+ elif event.key == pygame.K_l: # 'L' ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
58
+ loaded_manager = load_simulation()
59
+ if loaded_manager:
60
+ npc_manager = loaded_manager
61
+ # ๋ถˆ๋Ÿฌ์˜จ ๋ฐ์ดํ„ฐ๋กœ ์—”์ง„ ์žฌ์„ค์ •
62
+ village.npc_manager = npc_manager
63
+ engine.npc_manager = npc_manager
64
+ engine.selected_npc = None # ์„ ํƒ ์ดˆ๊ธฐํ™”
65
+ print("์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์ƒˆ๋กœ๊ณ ์นจํ–ˆ์Šต๋‹ˆ๋‹ค.")
66
+
67
+ elif event.key == pygame.K_ESCAPE:
68
  engine.clear_selected_npc() # ESC๋กœ ์„ ํƒ ํ•ด์ œ
69
+ elif event.type == pygame.MOUSEBUTTONDOWN:
70
+ engine.handle_click(pygame.mouse.get_pos()) # ๋งˆ์šฐ์Šค ํด๋ฆญ์œผ๋กœ NPC ์„ ํƒ
71
+
72
+ screen.fill((255, 255, 255))
73
+ engine.update()
74
+ engine.draw()
75
+ pygame.display.update()
76
+ clock.tick(10) # ์ดˆ๋‹น 10ํ”„๋ ˆ์ž„
77
 
78
+ # ์ข…๋ฃŒ ์ „์— ์ตœ์ข… ์ƒํƒœ ์ €์žฅ
79
+ save_simulation(npc_manager)
80
  pygame.quit()
81
  sys.exit()
82
 
npc_social_network/npc/emotion_config.py CHANGED
@@ -191,9 +191,9 @@ EMOTION_RELATION_IMPACT = {
191
  "attachment": 1.7,
192
  "anticipation": 0.7,
193
  "curiosity": 0.6,
194
- "nostalgia": 0.2,
195
- "bittersweet": 0.1,
196
- "rumination": 0.0,
197
  "groundedness": 0.5,
198
  "comfort": 0.6,
199
  }
 
191
  "attachment": 1.7,
192
  "anticipation": 0.7,
193
  "curiosity": 0.6,
194
+ "nostalgia": 0.4,
195
+ "bittersweet": 0.4,
196
+ "rumination": 0.4,
197
  "groundedness": 0.5,
198
  "comfort": 0.6,
199
  }
npc_social_network/npc/npc_base.py CHANGED
@@ -378,36 +378,46 @@ class NPC:
378
  if not recent_memories:
379
  return
380
 
 
 
381
  # Personality ๋ณ€ํ™” ๋ฐ˜์˜
382
  for mem in recent_memories:
383
- if not mem.emotion: continue
 
 
 
384
 
385
  # 1. ๊ฐ์ •์˜ ๊ธ์ •/๋ถ€์ •/์ธ์ง€์  ์†์„ฑ์— ๋”ฐ๋ฅธ ์˜ํ–ฅ ๋ฐฉํ–ฅ ๊ฒฐ์ •
386
  influence_vector = {"sensitive": 0.0, "stoic": 0.0, "cognitive_bias": 0.0}
387
- # (์ˆ˜์ • ํ•„์š”)๊ทผ๋ฐ ์ด๋Ÿฌ๋ฉด ๊ฐ ๊ฐ์ •, ๊ฐ์ •์˜ ์„ธ๊ธฐ ๋“ฑ๊ณผ ์ƒ๊ด€ ์—†์ด ๋ชจ๋‘ ์ผ๊ด„์ ์œผ๋กœ ์ ์šฉ๋˜๋Š”๊ฑฐ ์•„๋‹Œ๊ฐ€?
388
- # ์—ฌ๊ธฐ์„œ influence_vector ๊ฐ’์„ ์ดˆ๊ธฐํ™” ํ•˜๋ฉด ๊ณ„์† 0.0์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š”๊ฑฐ ์•„๋‹Œ๊ฐ€?
389
- # ๋…ผ๋ฆฌ์  ์‚ฌ๊ณ  ๊ฐ•ํ™”๊ฐ€ ์žˆ์œผ๋ฉด ๊ฐ์„ฑ์  ์‚ฌ๊ณ  ๊ฐ•ํ™”๋„ ์žˆ์–ด์•ผ์ง€
390
- # ์ตœ์†Œํ•œ MBTI๋กœ ๋ถ„๋ฅ˜ํ•  ์ •๋„๋Š” ๋‚˜์™€์•ผ๋˜๋Š”๊ฑฐ ์•„๋‹Œ๊ฐ€? ComplexEmotions ๊ฐ์ • ๋ชจ๋ธ์ด ์ •์ƒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธ ํ•„์š”
391
  if mem.emotion in POSITIVE_RELATION_EMOTIONS:
392
- influence_vector["sensitive"] -= 0.5 # ๊ธ์ •์  ๊ฒฝํ—˜์€ ๋ฏผ๊ฐ๋„๋ฅผ ๋‚ฎ์ถค
393
- influence_vector["stoic"] -= 0.3 # ๊ธ์ •์ ์ธ ๊ฒฝํ—˜์€ ๋‚ด์„ฑ์ ์ผ ํ•„์š”๋ฅผ ์ค„์ž„
 
394
  elif mem.emotion in NEGATIVE_RELATION_EMOTIONS:
395
- influence_vector["sensitive"] += 0.5 # ๋ถ€์ •์  ๊ฒฝํ—˜์€ ๋ฏผ๊ฐ๋„๋ฅผ ๋†’์ž„
396
- influence_vector["stoic"] += 0.3 # ๋ถ€์ •์  ๊ฒฝํ—˜์€ ๋‚ด์„ฑ์ ์œผ๋กœ ๋งŒ๋“ฆ
397
- elif mem.emotion in COGNITIVE_RELATION_EMOTIONS:
398
- influence_vector["cognitive_bias"] += 0.6 # ์ธ์ง€์  ๊ฒฝํ—˜์€ ๋…ผ๋ฆฌ์  ์‚ฌ๊ณ ๋ฅผ ๊ฐ•ํ™”
 
399
 
400
  # 2. ๋ณ€ํ™” ๊ฐ•๋„ ๊ณ„์‚ฐ (๊ธฐ์–ต์˜ ์ค‘์š”๋„์™€ ๋‚˜์ด์— ๋”ฐ๋ผ)
401
  age_factor = AGE_PROFILE.get(self.personality_stage, 1.0)
402
  change_strength = (mem.importance / 10.0) * age_factor
403
 
404
- # 3. ๊ณ„์‚ฐ๋œ ๋ณ€ํ™”๋Ÿ‰ ์ ์šฉ
405
- for trait, change in influence_vector.items():
 
 
 
 
 
406
  rate = self.personality_change_rate.get(trait, 0.003)
407
- delta = change * change_strength * rate
408
  self.personality[trait] = max(0.0, min(1.0, self.personality[trait] + delta))
409
 
410
- # 4. ๊ธฐ์ค€์„ ์œผ๋กœ ํšŒ๊ท€ (ํ•ญ์ƒ์„ฑ)
411
  base_decay = 0.001
412
  for trait in self.personality.keys():
413
  decay_rate = base_decay * (1.0 + self.personality.get("stoic", 0.0) - self.personality.get("sensitive", 0.0))
 
378
  if not recent_memories:
379
  return
380
 
381
+ total_influence = {"sensitive": 0.0, "stoic": 0.0, "cognitive_bias": 0.0}
382
+
383
  # Personality ๋ณ€ํ™” ๋ฐ˜์˜
384
  for mem in recent_memories:
385
+ if not mem.emotion or mem.emotion not in EMOTION_RELATION_IMPACT: continue
386
+
387
+ # ๊ฐ ๊ฐ์ •์˜ ๊ณ ์œ ํ•œ ์˜ํ–ฅ๋ ฅ(impact)์„ ๊ฐ€์ ธ์˜ด
388
+ emotion_impact = EMOTION_RELATION_IMPACT.get(mem.emotion, 0.0)
389
 
390
  # 1. ๊ฐ์ •์˜ ๊ธ์ •/๋ถ€์ •/์ธ์ง€์  ์†์„ฑ์— ๋”ฐ๋ฅธ ์˜ํ–ฅ ๋ฐฉํ–ฅ ๊ฒฐ์ •
391
  influence_vector = {"sensitive": 0.0, "stoic": 0.0, "cognitive_bias": 0.0}
392
+
393
+ # ๊ฐ์ • ์˜ํ–ฅ๋ ฅ์ด ์–‘์ˆ˜์ด๋ฉด(๊ธ์ •์  ๊ฐ์ •), ๋ฏผ๊ฐ๋„์™€ ๋‚ด์„ฑ์„ ๋‚ฎ์ถค
 
 
394
  if mem.emotion in POSITIVE_RELATION_EMOTIONS:
395
+ influence_vector["sensitive"] -= abs(emotion_impact) / 2.0 # ๊ธ์ •์  ๊ฒฝํ—˜์€ ๋ฏผ๊ฐ๋„๋ฅผ ๋‚ฎ์ถค
396
+ influence_vector["stoic"] -= abs(emotion_impact) / 4.0 # ๊ธ์ •์ ์ธ ๊ฒฝํ—˜์€ ๋‚ด์„ฑ์ ์ผ ํ•„์š”๋ฅผ ์ค„์ž„
397
+ # ๊ฐ์ • ์˜ํ–ฅ๋ ฅ์ด ์Œ์ˆ˜์ด๋ฉด(๋ถ€์ •์  ๊ฐ์ •), ๋ฏผ๊ฐ๋„์™€ ๋‚ด์„ฑ์„ ๋†’์ž„
398
  elif mem.emotion in NEGATIVE_RELATION_EMOTIONS:
399
+ influence_vector["sensitive"] += abs(emotion_impact) / 2.0 # ๋ถ€์ •์  ๊ฒฝํ—˜์€ ๋ฏผ๊ฐ๋„๋ฅผ ๋†’์ž„
400
+ influence_vector["stoic"] += abs(emotion_impact) / 4.0 # ๋ถ€์ •์  ๊ฒฝํ—˜์€ ๋‚ด์„ฑ์ ์œผ๋กœ ๋งŒ๋“ฆ
401
+ # ์ธ์ง€์  ๊ฐ์ •์€ cognitive_bias์— ์˜ํ–ฅ
402
+ if mem.emotion in COGNITIVE_RELATION_EMOTIONS:
403
+ influence_vector["cognitive_bias"] += 0.4 # ์ธ์ง€์  ๊ฒฝํ—˜์€ ๋…ผ๋ฆฌ์  ์‚ฌ๊ณ ๋ฅผ ๊ฐ•ํ™”
404
 
405
  # 2. ๋ณ€ํ™” ๊ฐ•๋„ ๊ณ„์‚ฐ (๊ธฐ์–ต์˜ ์ค‘์š”๋„์™€ ๋‚˜์ด์— ๋”ฐ๋ผ)
406
  age_factor = AGE_PROFILE.get(self.personality_stage, 1.0)
407
  change_strength = (mem.importance / 10.0) * age_factor
408
 
409
+ # 3. ์ด๋ฒˆ ๊ธฐ์–ต์œผ๋กœ ์ธํ•œ ์ตœ์ข… ๋ณ€ํ™”๋Ÿ‰ ๋ˆ„์ 
410
+ for trait in total_influence.keys():
411
+ total_influence[trait] += influence_vector[trait] * change_strength
412
+
413
+ # 4. ๋ˆ„์ ๋œ ๋ณ€ํ™”๋Ÿ‰์„ ์„ฑ๊ฒฉ์— ์ ์šฉ
414
+ for trait, total_change in total_influence.items():
415
+ if abs(total_change) > 0.001: # ์˜๋ฏธ์žˆ๋Š” ๋ณ€ํ™”๋งŒ ์ ์šฉ
416
  rate = self.personality_change_rate.get(trait, 0.003)
417
+ delta = total_change * rate
418
  self.personality[trait] = max(0.0, min(1.0, self.personality[trait] + delta))
419
 
420
+ # 5. ๊ธฐ์ค€์„ ์œผ๋กœ ํšŒ๊ท€ (ํ•ญ์ƒ์„ฑ)
421
  base_decay = 0.001
422
  for trait in self.personality.keys():
423
  decay_rate = base_decay * (1.0 + self.personality.get("stoic", 0.0) - self.personality.get("sensitive", 0.0))