humanda5 commited on
Commit
aabeb2d
·
1 Parent(s): 5b8b298

감정 고도화 테스트 중

Browse files
Files changed (2) hide show
  1. npc_social_network/npc/npc_base.py +83 -15
  2. test.ipynb +81 -2
npc_social_network/npc/npc_base.py CHANGED
@@ -17,7 +17,7 @@ class NPC:
17
  # npc 기억
18
  self.memory_store = MemoryStore()
19
 
20
- # 고차원 감정 상태 정의 (GoEmotions 기반)
21
  self.emotion_state = {
22
  # 기본 정서 (긍정)
23
  "core_positive":{
@@ -58,6 +58,46 @@ class NPC:
58
  "skepticism": 0 # 회의
59
  }
60
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
  # 확장 가능 속성
63
  # self.emotion = "neutral"
@@ -76,24 +116,52 @@ class NPC:
76
  x, y = self.get_position()
77
  screen.blit(self.image, (x * tile_size, y * tile_size))
78
 
79
- # 감정 상태에 따른 대사 생성 (대표 감정 하나 반영)
80
  def generate_dialogue(self):
81
- pass
82
-
83
- # 직업에 따른 기본 대사 생성
84
- def generate_dialogue(self):
85
- if self.job == "farmer":
86
- return "오늘은 밭에 나갈 날이군요!"
87
- elif self.job == "blacksmith":
88
- return "망치를 들고 일할 준비가 되었어요!"
89
- return "좋은 하루입니다."
90
 
91
- # NPC가 새로운 기억을 저장
92
- def remember(self, content: str, importance: int = 5, emotion: str = "중립"):
93
- memory = Memory(content=content, importance = importance, emotion=emotion)
94
  self.memory_store.add_memory(memory)
 
 
95
 
96
  # 저장된 모든 기억(단기+장기)을 리스트로 반환
97
  def recall(self):
98
  return [m.content for m in self.memory_store.get_all_memories()]
99
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  # npc 기억
18
  self.memory_store = MemoryStore()
19
 
20
+ # 고차원 감정 상태 정의 (GoEmotions 기반, 보여주기용)
21
  self.emotion_state = {
22
  # 기본 정서 (긍정)
23
  "core_positive":{
 
58
  "skepticism": 0 # 회의
59
  }
60
  }
61
+
62
+ # 감정별 회복 속도 (ms 단위가 아닌 단위당 감소 속도)
63
+ self.emotion_decay_rate = {
64
+ # 기본 정서 (긍정)
65
+ "joy": 1, # 기쁨
66
+ "satisfaction": 1, # 만족
67
+ "gratitude": 1, # 감사
68
+ "calm": 1, # 평온
69
+ "anticipation": 1, # 기대
70
+ "pride": 1, # 자부심
71
+ "connectedness": 1, # 유대감
72
+
73
+ # 기본 정서 (부정) - 느림
74
+ "sadness": 0.2, # 슬픔
75
+ "anger": 0.5, # 분노
76
+ "anxiety": 0.4, # 불안
77
+ "disgust": 0.8, # 혐오
78
+ "fear": 0.6, # 공포
79
+ "regret": 0.3, # 후회
80
+ "frustration": 0.5, # 좌절
81
+
82
+ # 사회적 감정
83
+ "jealousy": 0.4, # 질투
84
+ "shame": 0.4, # 수치심
85
+ "guilt": 0.4, # 죄책감
86
+ "compassion": 1, # 동정심
87
+ "awe": 1, # 경외심
88
+ "empathy": 1, # 공감
89
+
90
+ # 인지적 상태
91
+ "confusion": 0.8, # 혼란
92
+ "nervousness": 0.7, # 긴장
93
+ "apathy": 0.4, # 무관심
94
+ "excitement": 1.2, # 흥분
95
+ "immersion": 1.0, # 몰입
96
+ "skepticism": 0.5, # 회의
97
+ }
98
+
99
+ # 내부: float 감정 수치 관리용 버퍼
100
+ self._emotion_buffer = {emo: 0.0 for cat in self.emotion_state for emo in self.emotion_state[cat]}
101
 
102
  # 확장 가능 속성
103
  # self.emotion = "neutral"
 
116
  x, y = self.get_position()
117
  screen.blit(self.image, (x * tile_size, y * tile_size))
118
 
119
+ # 감정 상태와 직업에 따른 대사 생성 (대표 감정 하나 반영)
120
  def generate_dialogue(self):
121
+ dominant = self.get_dominant_emotion()
122
+ emotion_line = f"지금 저는 '{dominant}' 상태예요." if dominant else "기분이 안정돼 있어요."
123
+ job_line = {
124
+ "farmer": "밭일을 해야겠어요.",
125
+ "blacksmith": "대장간에 불을 지펴야겠군요."
126
+ }.get(self.job, "오늘도 바쁘네요.")
127
+ return f"{emotion_line} {job_line}"
 
 
128
 
129
+ # NPC가 새로운 기억을 저장하고 감정 상태에 반영
130
+ def remember(self, content: str, importance: int = 5, emotion: str = None):
131
+ memory = Memory(content=content, importance = importance, emotion=emotion or "neutral")
132
  self.memory_store.add_memory(memory)
133
+ if emotion:
134
+ self.update_emotion(emotion)
135
 
136
  # 저장된 모든 기억(단기+장기)을 리스트로 반환
137
  def recall(self):
138
  return [m.content for m in self.memory_store.get_all_memories()]
139
+
140
+ # 특정 감정을 감정 상태에 반영 (카테고리 기반)
141
+ def update_emotion(self, emotion: str, strength: int = 1):
142
+ if emotion in self._emotion_buffer:
143
+ self._emotion_buffer[emotion] += strength
144
+
145
+ # 시간이 지남에 따라 모든 감정이 서서히 감소
146
+ def decay_emotion(self):
147
+ for emotion in self._emotion_buffer:
148
+ rate = self.emotion_decay_rate.get(emotion, 1.0)
149
+ self._emotion_buffer[emotion] = max(0.0, self._emotion_buffer[emotion] - rate)
150
+
151
+ # 정수 기반 출력용 감정 상태 반환
152
+ def get_current_emotion_state(self):
153
+ display_state = {cat: {} for cat in self.emotion_state}
154
+ for cat in self.emotion_state:
155
+ for emo in self.emotion_state[cat]:
156
+ display_state[cat][emo] = float(self._emotion_buffer[emo])
157
+ return display_state
158
+
159
+ # 현재 가장 강한 감정 반환 (전체 감정 중 최댓값 1개)
160
+ def get_dominant_emotion(self):
161
+ max_value = 0.0
162
+ max_emotion = None
163
+ for emo, val in self._emotion_buffer.items():
164
+ if val > max_value:
165
+ max_value = val
166
+ max_emotion = emo
167
+ return max_emotion
test.ipynb CHANGED
@@ -2711,7 +2711,13 @@
2711
  "output_type": "stream",
2712
  "text": [
2713
  "pygame 2.6.1 (SDL 2.28.4, Python 3.11.11)\n",
2714
- "Hello from the pygame community. https://www.pygame.org/contribute.html\n"
 
 
 
 
 
 
2715
  ]
2716
  },
2717
  {
@@ -2727,7 +2733,7 @@
2727
  "name": "stderr",
2728
  "output_type": "stream",
2729
  "text": [
2730
- "c:\\Users\\stina\\.conda\\envs\\portfolio\\Lib\\site-packages\\IPython\\core\\interactiveshell.py:3678: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.\n",
2731
  " warn(\"To exit: use 'exit', 'quit', or Ctrl-D.\", stacklevel=1)\n"
2732
  ]
2733
  }
@@ -2745,6 +2751,79 @@
2745
  "\n",
2746
  "# town_hall.py는 __main__이 아니라 직접 실행되므로"
2747
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2748
  }
2749
  ],
2750
  "metadata": {
 
2711
  "output_type": "stream",
2712
  "text": [
2713
  "pygame 2.6.1 (SDL 2.28.4, Python 3.11.11)\n",
2714
+ "Hello from the pygame community. https://www.pygame.org/contribute.html\n",
2715
+ "\n",
2716
+ "👤 Elin (farmer)\n",
2717
+ " - 위치: (5, 4)\n",
2718
+ " - 대화: 오늘은 밭에 나갈 날이군요!\n",
2719
+ " - 기억: []\n",
2720
+ "아침 - Elin이(가) market에 도착했습니다.\n"
2721
  ]
2722
  },
2723
  {
 
2733
  "name": "stderr",
2734
  "output_type": "stream",
2735
  "text": [
2736
+ "C:\\Users\\human\\AppData\\Roaming\\Python\\Python311\\site-packages\\IPython\\core\\interactiveshell.py:3675: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.\n",
2737
  " warn(\"To exit: use 'exit', 'quit', or Ctrl-D.\", stacklevel=1)\n"
2738
  ]
2739
  }
 
2751
  "\n",
2752
  "# town_hall.py는 __main__이 아니라 직접 실행되므로"
2753
  ]
2754
+ },
2755
+ {
2756
+ "cell_type": "code",
2757
+ "execution_count": null,
2758
+ "id": "ac67ce84",
2759
+ "metadata": {},
2760
+ "outputs": [
2761
+ {
2762
+ "name": "stdout",
2763
+ "output_type": "stream",
2764
+ "text": [
2765
+ "초기 감정 상태:\n",
2766
+ "{'core_positive': {'joy': 0, 'satisfaction': 0, 'gratitude': 0, 'calm': 0, 'anticipation': 0, 'pride': 0, 'connectedness': 0}, 'core_negative': {'sadness': 0, 'anger': 0, 'anxiety': 0, 'disgust': 0, 'fear': 0, 'regret': 0, 'frustration': 0}, 'social_emotion': {'jealousy': 0, 'shame': 0, 'guilt': 0, 'compassion': 0, 'awe': 0, 'empathy': 0}, 'cognitive_state': {'confusion': 0, 'nervousness': 0, 'apathy': 0, 'excitement': 0, 'immersion': 0, 'skepticism': 0}}\n",
2767
+ "\n",
2768
+ "[1회 decay 후]\n",
2769
+ "{'core_positive': {'joy': 0, 'satisfaction': 0, 'gratitude': 0, 'calm': 0, 'anticipation': 0, 'pride': 0, 'connectedness': 0}, 'core_negative': {'sadness': 0, 'anger': 0, 'anxiety': 0, 'disgust': 0, 'fear': 0, 'regret': 0, 'frustration': 0}, 'social_emotion': {'jealousy': 0, 'shame': 0, 'guilt': 0, 'compassion': 0, 'awe': 0, 'empathy': 0}, 'cognitive_state': {'confusion': 0, 'nervousness': 0, 'apathy': 0, 'excitement': 0, 'immersion': 0, 'skepticism': 0}}\n",
2770
+ "\n",
2771
+ "[2회 decay 후]\n",
2772
+ "{'core_positive': {'joy': 0, 'satisfaction': 0, 'gratitude': 0, 'calm': 0, 'anticipation': 0, 'pride': 0, 'connectedness': 0}, 'core_negative': {'sadness': 0, 'anger': 0, 'anxiety': 0, 'disgust': 0, 'fear': 0, 'regret': 0, 'frustration': 0}, 'social_emotion': {'jealousy': 0, 'shame': 0, 'guilt': 0, 'compassion': 0, 'awe': 0, 'empathy': 0}, 'cognitive_state': {'confusion': 0, 'nervousness': 0, 'apathy': 0, 'excitement': 0, 'immersion': 0, 'skepticism': 0}}\n",
2773
+ "\n",
2774
+ "[3회 decay 후]\n",
2775
+ "{'core_positive': {'joy': 0, 'satisfaction': 0, 'gratitude': 0, 'calm': 0, 'anticipation': 0, 'pride': 0, 'connectedness': 0}, 'core_negative': {'sadness': 0, 'anger': 0, 'anxiety': 0, 'disgust': 0, 'fear': 0, 'regret': 0, 'frustration': 0}, 'social_emotion': {'jealousy': 0, 'shame': 0, 'guilt': 0, 'compassion': 0, 'awe': 0, 'empathy': 0}, 'cognitive_state': {'confusion': 0, 'nervousness': 0, 'apathy': 0, 'excitement': 0, 'immersion': 0, 'skepticism': 0}}\n",
2776
+ "\n",
2777
+ "[4회 decay 후]\n",
2778
+ "{'core_positive': {'joy': 0, 'satisfaction': 0, 'gratitude': 0, 'calm': 0, 'anticipation': 0, 'pride': 0, 'connectedness': 0}, 'core_negative': {'sadness': 0, 'anger': 0, 'anxiety': 0, 'disgust': 0, 'fear': 0, 'regret': 0, 'frustration': 0}, 'social_emotion': {'jealousy': 0, 'shame': 0, 'guilt': 0, 'compassion': 0, 'awe': 0, 'empathy': 0}, 'cognitive_state': {'confusion': 0, 'nervousness': 0, 'apathy': 0, 'excitement': 0, 'immersion': 0, 'skepticism': 0}}\n",
2779
+ "\n",
2780
+ "[5회 decay 후]\n",
2781
+ "{'core_positive': {'joy': 0, 'satisfaction': 0, 'gratitude': 0, 'calm': 0, 'anticipation': 0, 'pride': 0, 'connectedness': 0}, 'core_negative': {'sadness': 0, 'anger': 0, 'anxiety': 0, 'disgust': 0, 'fear': 0, 'regret': 0, 'frustration': 0}, 'social_emotion': {'jealousy': 0, 'shame': 0, 'guilt': 0, 'compassion': 0, 'awe': 0, 'empathy': 0}, 'cognitive_state': {'confusion': 0, 'nervousness': 0, 'apathy': 0, 'excitement': 0, 'immersion': 0, 'skepticism': 0}}\n"
2782
+ ]
2783
+ }
2784
+ ],
2785
+ "source": [
2786
+ "# 1. 경로 추가\n",
2787
+ "import sys, os\n",
2788
+ "sys.path.append(os.path.abspath(\".\")) # 프로젝트 루트 경로\n",
2789
+ "\n",
2790
+ "# 2. 클래스 import\n",
2791
+ "from npc_social_network.npc.npc_base import NPC\n",
2792
+ "\n",
2793
+ "# 3. NPC 생성 및 감정 입력\n",
2794
+ "npc = NPC(name=\"아린\", job=\"farmer\", path=[(0,0)], image=None)\n",
2795
+ "npc.remember(\"플레이어가 모욕함\", importance=6, emotion=\"anger\")\n",
2796
+ "npc.remember(\"무서운 소리를 들음\", importance=5, emotion=\"fear\")\n",
2797
+ "npc.remember(\"친구가 칭찬함\", importance=5, emotion=\"pride\")\n",
2798
+ "\n",
2799
+ "print(\"초기 감정 상태:\")\n",
2800
+ "print(npc.get_current_emotion_state())\n",
2801
+ "\n",
2802
+ "# 4. decay 반복 적용\n",
2803
+ "for step in range(1, 6):\n",
2804
+ " npc.decay_emotion()\n",
2805
+ " print(f\"\\n[{step}회 decay 후]\")\n",
2806
+ " print(npc.get_current_emotion_state())"
2807
+ ]
2808
+ },
2809
+ {
2810
+ "cell_type": "code",
2811
+ "execution_count": 5,
2812
+ "id": "cc6f2948",
2813
+ "metadata": {},
2814
+ "outputs": [
2815
+ {
2816
+ "name": "stdout",
2817
+ "output_type": "stream",
2818
+ "text": [
2819
+ "d:\\private\\Portfolio\\npc_social_network\\npc\\npc_base.py\n"
2820
+ ]
2821
+ }
2822
+ ],
2823
+ "source": [
2824
+ "import npc_social_network.npc.npc_base as base\n",
2825
+ "print(base.__file__)"
2826
+ ]
2827
  }
2828
  ],
2829
  "metadata": {