zshashz commited on
Commit
8455be2
·
1 Parent(s): d0d2794
Files changed (2) hide show
  1. index.html +104 -46
  2. test_x.html +227 -0
index.html CHANGED
@@ -268,52 +268,110 @@
268
 
269
  <div class="tooltip" id="tooltip"></div>
270
 
271
- <script>
272
- class ShyGuySimulator {
273
- constructor(apiKey) {
274
- this.apiKey = apiKey;
275
- this.state = {
276
- confidence: 0,
277
- anxiety: 100,
278
- drinks: 0,
279
- time: new Date(2024, 0, 1, 20, 0),
280
- playerPos: { x: 0, y: 9 },
281
- moveSpeed: 1,
282
- isProcessing: false,
283
- hasSpokenToGirl: false,
284
- locations: {
285
- bar: [{ x: 8, y: 1 }, { x: 9, y: 1 }],
286
- dj: [{ x: 4, y: 0 }, { x: 5, y: 0 }],
287
- girl: [{ x: 9, y: 8 }],
288
- sister: [{ x: 2, y: 5 }],
289
- obstacles: [
290
- { x: 3, y: 3 }, { x: 4, y: 3 },
291
- { x: 6, y: 6 }, { x: 7, y: 6 }
292
- ]
293
- }
294
- };
295
-
296
- this.context = [
297
- {
298
- role: 'system',
299
- content: `You are roleplaying as a shy and anxious guy at a homecoming party.
300
- You're standing near the entrance, and the girl you like is across the room.
301
- Your responses should reflect your social anxiety and reluctance to approach her.
302
- Keep responses concise (max 2-3 sentences) and natural.
303
- Express hesitation, worry, and self-doubt while reacting to the wingman's encouragement.
304
- Current state: Confidence: ${this.state.confidence}%, Anxiety: ${this.state.anxiety}%`
305
- }
306
- ];
307
-
308
- this.initialize();
309
- this.initializeGrid();
310
- }
311
-
312
- initialize() {
313
- this.addMessage("Hey! I'll be your wingman tonight. I see that girl you like over there - let's help you talk to her!", 'wingman');
314
- this.addMessage("I... I don't know about this. Maybe I should just go home...", 'shyguy');
315
- this.updateStats();
316
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
 
318
  initializeGrid() {
319
  const grid = document.getElementById('party-grid');
 
268
 
269
  <div class="tooltip" id="tooltip"></div>
270
 
271
+ <script>
272
+ class ShyGuySimulator {
273
+ constructor(apiKey) {
274
+ this.apiKey = apiKey;
275
+ this.state = {
276
+ confidence: 0,
277
+ anxiety: 100,
278
+ drinks: 0,
279
+ time: new Date(2024, 0, 1, 20, 0),
280
+ playerPos: { x: 0, y: 9 },
281
+ moveSpeed: 1,
282
+ isProcessing: false,
283
+ hasSpokenToGirl: false,
284
+ lastEmotion: 'anxious',
285
+ locations: {
286
+ bar: [{ x: 8, y: 1 }, { x: 9, y: 1 }],
287
+ dj: [{ x: 4, y: 0 }, { x: 5, y: 0 }],
288
+ girl: [{ x: 9, y: 8 }],
289
+ sister: [{ x: 2, y: 5 }],
290
+ obstacles: [
291
+ { x: 3, y: 3 }, { x: 4, y: 3 },
292
+ { x: 6, y: 6 }, { x: 7, y: 6 }
293
+ ]
294
+ }
295
+ };
296
+
297
+ this.context = [{
298
+ role: 'system',
299
+ content: `You are roleplaying as a shy guy at a party, providing both dialogue and movement decisions.
300
+ The party is on a 10x10 grid. You start at (0,9), and the girl you like is at (9,8).
301
+ ALWAYS structure your responses in this exact format:
302
+ {
303
+ "dialogue": "Your spoken response here",
304
+ "movement": {
305
+ "x": number (-1, 0, or 1 for movement),
306
+ "y": number (-1, 0, or 1 for movement)
307
+ },
308
+ "emotion": "anxious|nervous|slightly_confident|confident"
309
+ }
310
+
311
+ Rules:
312
+ 1. When drinks > 2, be more likely to move toward the girl
313
+ 2. When confidence < 30, prefer to move away or stay still
314
+ 3. Keep dialogue natural and brief (1-2 sentences)
315
+ 4. Movement should reflect emotional state
316
+ 5. Account for obstacles at: [(3,3), (4,3), (6,6), (7,6)]
317
+ 6. Consider locations of: bar(8,1 & 9,1), DJ(4,0 & 5,0), sister(2,5)
318
+ Current state: Confidence: ${this.state.confidence}%, Anxiety: ${this.state.anxiety}%`
319
+ }];
320
+
321
+ this.initialize();
322
+ this.initializeGrid();
323
+ this.startAutonomousMovement();
324
+ }
325
+
326
+ initialize() {
327
+ this.addMessage("Hey! I'll be your wingman tonight. I see that girl you like over there - let's help you talk to her!", 'wingman');
328
+ this.addMessage("I... I don't know about this. Maybe I should just go home...", 'shyguy');
329
+ this.updateStats();
330
+ }
331
+
332
+ startAutonomousMovement() {
333
+ this.movementInterval = setInterval(async () => {
334
+ if (!this.state.isProcessing && !this.state.hasSpokenToGirl) {
335
+ await this.getNextMove();
336
+ }
337
+ }, 5000);
338
+ }
339
+
340
+ stopAutonomousMovement() {
341
+ if (this.movementInterval) {
342
+ clearInterval(this.movementInterval);
343
+ }
344
+ }
345
+
346
+ async getNextMove() {
347
+ try {
348
+ const response = await this.callMistralAPI();
349
+ let parsedResponse;
350
+
351
+ try {
352
+ parsedResponse = JSON.parse(response);
353
+ } catch (e) {
354
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
355
+ if (jsonMatch) {
356
+ parsedResponse = JSON.parse(jsonMatch[0]);
357
+ } else {
358
+ throw new Error('Could not parse LLM response');
359
+ }
360
+ }
361
+
362
+ this.state.lastEmotion = parsedResponse.emotion;
363
+ this.addMessage(parsedResponse.dialogue, 'shyguy');
364
+
365
+ if (parsedResponse.movement) {
366
+ await this.movePlayer(
367
+ parsedResponse.movement.x,
368
+ parsedResponse.movement.y
369
+ );
370
+ }
371
+ } catch (error) {
372
+ console.error('Error getting next move:', error);
373
+ }
374
+ }
375
 
376
  initializeGrid() {
377
  const grid = document.getElementById('party-grid');
test_x.html ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // The HTML and CSS remain the same until the ShyGuySimulator class
2
+
3
+ class ShyGuySimulator {
4
+ constructor(apiKey) {
5
+ this.apiKey = apiKey;
6
+ this.state = {
7
+ confidence: 0,
8
+ anxiety: 100,
9
+ drinks: 0,
10
+ time: new Date(2024, 0, 1, 20, 0),
11
+ playerPos: { x: 0, y: 9 },
12
+ moveSpeed: 1,
13
+ isProcessing: false,
14
+ hasSpokenToGirl: false,
15
+ lastEmotion: 'anxious',
16
+ locations: {
17
+ bar: [{ x: 8, y: 1 }, { x: 9, y: 1 }],
18
+ dj: [{ x: 4, y: 0 }, { x: 5, y: 0 }],
19
+ girl: [{ x: 9, y: 8 }],
20
+ sister: [{ x: 2, y: 5 }],
21
+ obstacles: [
22
+ { x: 3, y: 3 }, { x: 4, y: 3 },
23
+ { x: 6, y: 6 }, { x: 7, y: 6 }
24
+ ]
25
+ }
26
+ };
27
+
28
+ this.context = [{
29
+ role: 'system',
30
+ content: `You are roleplaying as a shy guy at a party, providing both dialogue and movement decisions.
31
+ The party is on a 10x10 grid. You start at (0,9), and the girl you like is at (9,8).
32
+ ALWAYS structure your responses in this exact format:
33
+ {
34
+ "dialogue": "Your spoken response here",
35
+ "movement": {
36
+ "x": number (-1, 0, or 1 for movement),
37
+ "y": number (-1, 0, or 1 for movement)
38
+ },
39
+ "emotion": "anxious|nervous|slightly_confident|confident"
40
+ }
41
+
42
+ Rules:
43
+ 1. When drinks > 2, be more likely to move toward the girl
44
+ 2. When confidence < 30, prefer to move away or stay still
45
+ 3. Keep dialogue natural and brief (1-2 sentences)
46
+ 4. Movement should reflect emotional state
47
+ 5. Account for obstacles at: [(3,3), (4,3), (6,6), (7,6)]
48
+ 6. Consider locations of: bar(8,1 & 9,1), DJ(4,0 & 5,0), sister(2,5)
49
+ Current state: Confidence: ${this.state.confidence}%, Anxiety: ${this.state.anxiety}%`
50
+ }];
51
+
52
+ this.initialize();
53
+ this.initializeGrid();
54
+ this.startAutonomousMovement();
55
+ }
56
+
57
+ // Add autonomous movement
58
+ startAutonomousMovement() {
59
+ this.movementInterval = setInterval(async () => {
60
+ if (!this.state.isProcessing && !this.state.hasSpokenToGirl) {
61
+ await this.getNextMove();
62
+ }
63
+ }, 5000); // Move every 5 seconds
64
+ }
65
+
66
+ stopAutonomousMovement() {
67
+ if (this.movementInterval) {
68
+ clearInterval(this.movementInterval);
69
+ }
70
+ }
71
+
72
+ async getNextMove() {
73
+ try {
74
+ const response = await this.callMistralAPI();
75
+ let parsedResponse;
76
+
77
+ try {
78
+ // Try to parse the response as JSON
79
+ parsedResponse = JSON.parse(response);
80
+ } catch (e) {
81
+ // If parsing fails, try to extract JSON from the text
82
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
83
+ if (jsonMatch) {
84
+ parsedResponse = JSON.parse(jsonMatch[0]);
85
+ } else {
86
+ throw new Error('Could not parse LLM response');
87
+ }
88
+ }
89
+
90
+ // Update emotional state
91
+ this.state.lastEmotion = parsedResponse.emotion;
92
+
93
+ // Add the dialogue
94
+ this.addMessage(parsedResponse.dialogue, 'shyguy');
95
+
96
+ // Execute the movement
97
+ if (parsedResponse.movement) {
98
+ await this.movePlayer(
99
+ parsedResponse.movement.x,
100
+ parsedResponse.movement.y
101
+ );
102
+ }
103
+ } catch (error) {
104
+ console.error('Error getting next move:', error);
105
+ }
106
+ }
107
+
108
+ async handleInput(userInput) {
109
+ if (this.state.isProcessing) return;
110
+ this.state.isProcessing = true;
111
+
112
+ try {
113
+ if (!userInput.trim()) throw new Error("Please enter some text");
114
+
115
+ this.addMessage(userInput, 'wingman');
116
+ this.addLoadingMessage();
117
+
118
+ const currentState = `Current state:
119
+ Confidence: ${this.state.confidence}%,
120
+ Anxiety: ${this.state.anxiety}%,
121
+ Drinks: ${this.state.drinks},
122
+ Position: (${this.state.playerPos.x},${this.state.playerPos.y}),
123
+ Location: ${this.getLocationDescription()}`;
124
+
125
+ this.context.push({
126
+ role: 'user',
127
+ content: `${userInput}\n\n${currentState}`
128
+ });
129
+
130
+ await this.getNextMove();
131
+
132
+ } catch (error) {
133
+ this.removeLoadingMessage();
134
+ this.addMessage(`Error: ${error.message}`, 'error');
135
+ console.error('Error:', error);
136
+ } finally {
137
+ this.state.isProcessing = false;
138
+ }
139
+ }
140
+
141
+ async movePlayer(dx, dy) {
142
+ let newX = this.state.playerPos.x + dx * this.state.moveSpeed;
143
+ let newY = this.state.playerPos.y + dy * this.state.moveSpeed;
144
+
145
+ // Check boundaries
146
+ newX = Math.max(0, Math.min(9, newX));
147
+ newY = Math.max(0, Math.min(9, newY));
148
+
149
+ // Check obstacles
150
+ if (this.isLocation(newX, newY, 'obstacles')) {
151
+ return;
152
+ }
153
+
154
+ // Random stumble when drunk
155
+ if (this.state.drinks >= 3) {
156
+ const stumbleChance = (this.state.drinks - 2) * 0.1;
157
+ if (Math.random() < stumbleChance) {
158
+ const randomDir = Math.random() < 0.5 ? 1 : -1;
159
+ if (Math.random() < 0.5) {
160
+ newX += randomDir;
161
+ } else {
162
+ newY += randomDir;
163
+ }
164
+ newX = Math.max(0, Math.min(9, newX));
165
+ newY = Math.max(0, Math.min(9, newY));
166
+ }
167
+ }
168
+
169
+ // Update position
170
+ this.state.playerPos = { x: newX, y: newY };
171
+
172
+ // Handle location interactions
173
+ await this.handleLocationInteraction(newX, newY);
174
+
175
+ // Advance time
176
+ this.state.time = new Date(this.state.time.getTime() + 2 * 60000);
177
+
178
+ this.updateStats();
179
+ this.initializeGrid();
180
+ }
181
+
182
+ async handleLocationInteraction(x, y) {
183
+ if (this.isLocation(x, y, 'bar')) {
184
+ this.state.drinks++;
185
+ this.state.confidence = Math.min(100, this.state.confidence + 15);
186
+ this.state.anxiety = Math.max(0, this.state.anxiety - 10);
187
+ this.state.moveSpeed = Math.min(2, 1 + this.state.drinks * 0.2);
188
+
189
+ if (this.state.drinks > 5) {
190
+ this.state.confidence = Math.max(0, this.state.confidence - 5);
191
+ await this.handleInput("*Starting to feel really dizzy...*");
192
+ }
193
+ }
194
+
195
+ if (this.isLocation(x, y, 'sister')) {
196
+ this.state.confidence = Math.min(100, this.state.confidence + 20);
197
+ this.state.anxiety = Math.max(0, this.state.anxiety - 15);
198
+ }
199
+
200
+ if (this.isLocation(x, y, 'dj')) {
201
+ this.state.confidence = Math.min(100, this.state.confidence + 10);
202
+ this.state.anxiety = Math.max(0, this.state.anxiety - 5);
203
+ }
204
+
205
+ if (this.isLocation(x, y, 'girl')) {
206
+ if (this.state.confidence >= 70 && this.state.anxiety <= 50) {
207
+ this.gameWon();
208
+ } else {
209
+ this.state.playerPos = {
210
+ x: Math.max(0, x - 2),
211
+ y: Math.max(0, y - 2)
212
+ };
213
+ this.state.anxiety += 15;
214
+ this.state.confidence = Math.max(0, this.state.confidence - 10);
215
+ }
216
+ }
217
+ }
218
+
219
+ gameWon() {
220
+ this.stopAutonomousMovement();
221
+ // Rest of gameWon implementation remains the same
222
+ }
223
+
224
+ // Rest of the class implementation remains the same
225
+ }
226
+
227
+ // The rest of the code (event listeners, etc.) remains the same