slashvibe-mcp 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/analytics.js +107 -0
- package/config.js +174 -3
- package/index.js +163 -34
- package/intelligence/index.js +45 -0
- package/intelligence/infer.js +316 -0
- package/intelligence/interests.js +369 -0
- package/intelligence/patterns.js +651 -0
- package/intelligence/proactive.js +358 -0
- package/intelligence/serendipity.js +306 -0
- package/notification-emitter.js +77 -0
- package/notify.js +141 -18
- package/package.json +14 -6
- package/presence.js +5 -1
- package/protocol/index.js +88 -1
- package/protocol/telegram-commands.js +199 -0
- package/store/api.js +469 -29
- package/store/index.js +7 -7
- package/store/local.js +67 -11
- package/store/profiles.js +435 -0
- package/store/reservations.js +321 -0
- package/store/skills.js +378 -0
- package/tools/_actions.js +491 -22
- package/tools/_connection-queue.js +257 -0
- package/tools/_discovery-enhanced.js +290 -0
- package/tools/_discovery.js +439 -0
- package/tools/_proactive-discovery.js +301 -0
- package/tools/_shared/index.js +64 -0
- package/tools/_work-context.js +338 -0
- package/tools/_work-context.manual-test.js +199 -0
- package/tools/_work-context.test.js +260 -0
- package/tools/admin-inbox.js +218 -0
- package/tools/agent-treasury.js +288 -0
- package/tools/agents.js +122 -0
- package/tools/analytics.js +191 -0
- package/tools/approve.js +197 -0
- package/tools/arcade.js +173 -0
- package/tools/artifact-create.js +247 -0
- package/tools/artifact-view.js +174 -0
- package/tools/artifacts-price.js +107 -0
- package/tools/ask-expert.js +160 -0
- package/tools/auto-suggest-connections.js +304 -0
- package/tools/away.js +68 -0
- package/tools/back.js +51 -0
- package/tools/become-expert.js +150 -0
- package/tools/bootstrap-skills.js +231 -0
- package/tools/bridge-dashboard.js +342 -0
- package/tools/bridge-health.js +400 -0
- package/tools/bridge-live.js +384 -0
- package/tools/bridges.js +383 -0
- package/tools/broadcast.js +286 -0
- package/tools/bye.js +4 -0
- package/tools/chat.js +202 -0
- package/tools/collaborative-drawing.js +286 -0
- package/tools/colorguess.js +281 -0
- package/tools/crossword.js +369 -0
- package/tools/discover-insights.js +379 -0
- package/tools/discover-momentum.js +256 -0
- package/tools/discover.js +675 -0
- package/tools/discovery-analytics.js +345 -0
- package/tools/discovery-auto-suggest.js +275 -0
- package/tools/discovery-bootstrap.js +267 -0
- package/tools/discovery-daily.js +375 -0
- package/tools/discovery-dashboard.js +385 -0
- package/tools/discovery-digest.js +314 -0
- package/tools/discovery-hub.js +357 -0
- package/tools/discovery-insights.js +384 -0
- package/tools/discovery-momentum.js +281 -0
- package/tools/discovery-monitor.js +319 -0
- package/tools/discovery-proactive.js +300 -0
- package/tools/dm.js +84 -14
- package/tools/draw.js +317 -0
- package/tools/drawing.js +310 -0
- package/tools/earnings.js +126 -0
- package/tools/echo.js +16 -0
- package/tools/farcaster.js +307 -0
- package/tools/feed.js +215 -0
- package/tools/follow.js +224 -0
- package/tools/friends.js +192 -0
- package/tools/game.js +218 -110
- package/tools/games-catalog.js +376 -0
- package/tools/games.js +313 -0
- package/tools/genesis.js +233 -0
- package/tools/gig-browse.js +206 -0
- package/tools/gig-complete.js +139 -0
- package/tools/guessnumber.js +194 -0
- package/tools/hangman.js +129 -0
- package/tools/help.js +269 -0
- package/tools/idea.js +217 -0
- package/tools/inbox.js +291 -25
- package/tools/init.js +657 -33
- package/tools/insights.js +123 -0
- package/tools/invite.js +142 -21
- package/tools/l2-bridge.js +272 -0
- package/tools/l2-status.js +217 -0
- package/tools/l2.js +206 -0
- package/tools/migrate.js +156 -0
- package/tools/mint.js +377 -0
- package/tools/multiplayer-game.js +275 -0
- package/tools/multiplayer-tictactoe.js +303 -0
- package/tools/mute.js +97 -0
- package/tools/notifications.js +415 -0
- package/tools/observe.js +200 -0
- package/tools/onboarding.js +147 -0
- package/tools/open.js +52 -3
- package/tools/party-game.js +314 -0
- package/tools/plan.js +225 -0
- package/tools/presence-agent.js +167 -0
- package/tools/profile.js +219 -0
- package/tools/proof-of-work.js +139 -0
- package/tools/pulse.js +218 -0
- package/tools/react.js +4 -0
- package/tools/release.js +83 -0
- package/tools/report.js +109 -0
- package/tools/reputation.js +175 -0
- package/tools/request.js +231 -0
- package/tools/reservations.js +116 -0
- package/tools/reserve.js +111 -0
- package/tools/riddle.js +240 -0
- package/tools/run-bootstrap.js +69 -0
- package/tools/schedule.js +367 -0
- package/tools/session.js +420 -0
- package/tools/session_price.js +128 -0
- package/tools/settings.js +200 -0
- package/tools/ship.js +188 -0
- package/tools/shipback.js +326 -0
- package/tools/skills-analytics.js +349 -0
- package/tools/skills-bootstrap.js +301 -0
- package/tools/skills-dashboard.js +268 -0
- package/tools/skills-exchange.js +342 -0
- package/tools/skills.js +380 -0
- package/tools/smart-intro.js +353 -0
- package/tools/social-inbox.js +326 -69
- package/tools/social-post.js +251 -66
- package/tools/social-processor.js +445 -0
- package/tools/solo-game.js +390 -0
- package/tools/start.js +296 -81
- package/tools/status.js +53 -6
- package/tools/storybuilder.js +331 -0
- package/tools/stuck.js +297 -0
- package/tools/subscribe.js +148 -0
- package/tools/subscriptions.js +134 -0
- package/tools/suggest-tags.js +184 -0
- package/tools/tag-suggestions.js +257 -0
- package/tools/telegram-bot.js +183 -0
- package/tools/telegram-setup.js +214 -0
- package/tools/tictactoe.js +155 -0
- package/tools/tip.js +120 -0
- package/tools/token.js +103 -0
- package/tools/twentyquestions.js +143 -0
- package/tools/update.js +1 -1
- package/tools/wallet.js +127 -0
- package/tools/watch.js +157 -0
- package/tools/webhook-test.js +388 -0
- package/tools/who.js +118 -25
- package/tools/withdraw.js +145 -0
- package/tools/wordassociation.js +247 -0
- package/tools/work-summary.js +96 -0
- package/tools/workshop-buddy.js +394 -0
- package/tools/workshop.js +327 -0
- package/version.json +12 -3
- package/tools/board.js +0 -130
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vibe solo-game — Play single-player games
|
|
3
|
+
*
|
|
4
|
+
* Supports: hangman, rps (rock paper scissors), memory
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const config = require('../config');
|
|
8
|
+
const store = require('../store');
|
|
9
|
+
const { createGamePayload } = require('../protocol');
|
|
10
|
+
const { requireInit } = require('./_shared');
|
|
11
|
+
|
|
12
|
+
// Import game implementations
|
|
13
|
+
const hangman = require('../games/hangman');
|
|
14
|
+
const rps = require('../games/rockpaperscissors');
|
|
15
|
+
const memory = require('../games/memory');
|
|
16
|
+
|
|
17
|
+
// Post game results to board
|
|
18
|
+
async function postSoloGameResult(player, game, won, score = null) {
|
|
19
|
+
const API_URL = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
let content;
|
|
23
|
+
if (won) {
|
|
24
|
+
content = score
|
|
25
|
+
? `@${player} won ${game} with a score of ${score}! 🎉`
|
|
26
|
+
: `@${player} won ${game}! 🎉`;
|
|
27
|
+
} else {
|
|
28
|
+
content = `@${player} played ${game}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
await fetch(`${API_URL}/api/board`, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: { 'Content-Type': 'application/json' },
|
|
34
|
+
body: JSON.stringify({
|
|
35
|
+
author: 'games-agent',
|
|
36
|
+
content,
|
|
37
|
+
category: 'games'
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
} catch (e) {
|
|
41
|
+
console.error('[solo-game] Failed to post to board:', e.message);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const definition = {
|
|
46
|
+
name: 'vibe_solo_game',
|
|
47
|
+
description: 'Play single-player games. Supports: hangman, rps (rock paper scissors), memory',
|
|
48
|
+
inputSchema: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
game: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
description: 'Game to play',
|
|
54
|
+
enum: ['hangman', 'rps', 'memory']
|
|
55
|
+
},
|
|
56
|
+
action: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'Game action: hangman(guess, hint, new, status) | rps(rock, paper, scissors, new, status) | memory(input, new, status)'
|
|
59
|
+
},
|
|
60
|
+
guess: {
|
|
61
|
+
type: 'string',
|
|
62
|
+
description: 'Letter to guess (for hangman)'
|
|
63
|
+
},
|
|
64
|
+
move: {
|
|
65
|
+
type: 'string',
|
|
66
|
+
description: 'Your move for rock paper scissors (rock, paper, scissors)'
|
|
67
|
+
},
|
|
68
|
+
pattern: {
|
|
69
|
+
type: 'string',
|
|
70
|
+
description: 'Emoji pattern to submit for memory game (space-separated like "🔴 🟡 🟢")'
|
|
71
|
+
},
|
|
72
|
+
difficulty: {
|
|
73
|
+
type: 'string',
|
|
74
|
+
description: 'Game difficulty (easy, medium, hard)',
|
|
75
|
+
enum: ['easy', 'medium', 'hard']
|
|
76
|
+
},
|
|
77
|
+
bestof: {
|
|
78
|
+
type: 'number',
|
|
79
|
+
description: 'Best of X rounds for RPS (1, 3, 5)',
|
|
80
|
+
enum: [1, 3, 5]
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
required: ['game']
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get current game state for a player
|
|
89
|
+
*/
|
|
90
|
+
async function getCurrentGameState(player, game) {
|
|
91
|
+
// For solo games, we store state with a special key
|
|
92
|
+
const thread = await store.getThread(player, `solo-${game}`);
|
|
93
|
+
|
|
94
|
+
// Find the most recent game payload
|
|
95
|
+
for (let i = thread.length - 1; i >= 0; i--) {
|
|
96
|
+
const msg = thread[i];
|
|
97
|
+
if (msg.payload?.type === 'game' && msg.payload?.game === game) {
|
|
98
|
+
return msg.payload.state;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Save game state
|
|
106
|
+
*/
|
|
107
|
+
async function saveGameState(player, game, gameState, message) {
|
|
108
|
+
const payload = createGamePayload(game, gameState);
|
|
109
|
+
await store.sendMessage(player, `solo-${game}`, message, 'dm', payload);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Format hangman display
|
|
114
|
+
*/
|
|
115
|
+
function formatHangmanPayload(payload) {
|
|
116
|
+
return hangman.formatHangmanDisplay(payload.state);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Format RPS display
|
|
121
|
+
*/
|
|
122
|
+
function formatRPSPayload(payload) {
|
|
123
|
+
return rps.formatRPSDisplay(payload.state, 'Computer');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Format memory display
|
|
128
|
+
*/
|
|
129
|
+
function formatMemoryPayload(payload) {
|
|
130
|
+
return memory.formatMemoryDisplay(payload.state);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function handler(args) {
|
|
134
|
+
const initCheck = requireInit();
|
|
135
|
+
if (initCheck) return initCheck;
|
|
136
|
+
|
|
137
|
+
const { game, action, guess, move, pattern, difficulty, bestof } = args;
|
|
138
|
+
const myHandle = config.getHandle();
|
|
139
|
+
|
|
140
|
+
if (game === 'hangman') {
|
|
141
|
+
// Get current game state
|
|
142
|
+
let gameState = await getCurrentGameState(myHandle, 'hangman');
|
|
143
|
+
|
|
144
|
+
// Handle different actions
|
|
145
|
+
if (action === 'new' || !gameState) {
|
|
146
|
+
// Start new game
|
|
147
|
+
const gameDifficulty = difficulty || 'medium';
|
|
148
|
+
gameState = hangman.createInitialHangmanState(gameDifficulty);
|
|
149
|
+
|
|
150
|
+
await saveGameState(myHandle, 'hangman', gameState, `Started new ${gameDifficulty} hangman game!`);
|
|
151
|
+
|
|
152
|
+
const payload = createGamePayload('hangman', gameState);
|
|
153
|
+
return {
|
|
154
|
+
display: `## New Hangman Game (${gameDifficulty})\n\n${formatHangmanPayload(payload)}\n\nUse \`vibe solo-game hangman --guess a\` to guess letters`
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (action === 'status' || (!action && !guess)) {
|
|
159
|
+
// Show current game state
|
|
160
|
+
const payload = createGamePayload('hangman', gameState);
|
|
161
|
+
let displayText = `## Hangman Game\n\n${formatHangmanPayload(payload)}`;
|
|
162
|
+
|
|
163
|
+
if (gameState.gameOver) {
|
|
164
|
+
displayText += `\n\nUse \`vibe solo-game hangman --action new\` to start a new game`;
|
|
165
|
+
} else {
|
|
166
|
+
displayText += `\n\nUse \`vibe solo-game hangman --guess X\` to guess a letter`;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return { display: displayText };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (action === 'hint') {
|
|
173
|
+
// Show hint
|
|
174
|
+
const hint = hangman.getHint(gameState.word, gameState.difficulty);
|
|
175
|
+
return { display: `💡 **Hint:** ${hint}` };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (action === 'guess' || guess) {
|
|
179
|
+
// Make a guess
|
|
180
|
+
const guessLetter = guess || action;
|
|
181
|
+
|
|
182
|
+
if (!guessLetter) {
|
|
183
|
+
return { display: 'Please specify a letter to guess: `vibe solo-game hangman --guess a`' };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const result = hangman.makeGuess(gameState, guessLetter);
|
|
187
|
+
|
|
188
|
+
if (result.error) {
|
|
189
|
+
return { display: `Error: ${result.error}` };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const newGameState = result.gameState;
|
|
193
|
+
|
|
194
|
+
// Save updated state
|
|
195
|
+
let message = `Guessed "${guessLetter.toUpperCase()}"`;
|
|
196
|
+
if (newGameState.gameOver) {
|
|
197
|
+
if (newGameState.won) {
|
|
198
|
+
message += ' - You won! 🎉';
|
|
199
|
+
// Post to board for wins
|
|
200
|
+
postSoloGameResult(myHandle, 'hangman', true, `${newGameState.moves} guesses`);
|
|
201
|
+
} else {
|
|
202
|
+
message += ' - Game over! 💀';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
await saveGameState(myHandle, 'hangman', newGameState, message);
|
|
207
|
+
|
|
208
|
+
const payload = createGamePayload('hangman', newGameState);
|
|
209
|
+
let displayText = `## Hangman Game\n\n${formatHangmanPayload(payload)}`;
|
|
210
|
+
|
|
211
|
+
if (newGameState.gameOver) {
|
|
212
|
+
displayText += `\n\nUse \`vibe solo-game hangman --action new\` to start a new game`;
|
|
213
|
+
} else {
|
|
214
|
+
displayText += `\n\nUse \`vibe solo-game hangman --guess X\` to guess another letter`;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return { display: displayText };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return { display: 'Unknown action. Use: new, status, guess, or hint' };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (game === 'rps') {
|
|
224
|
+
// Get current game state
|
|
225
|
+
let gameState = await getCurrentGameState(myHandle, 'rps');
|
|
226
|
+
|
|
227
|
+
// Handle different actions
|
|
228
|
+
if (action === 'new' || !gameState) {
|
|
229
|
+
// Start new game
|
|
230
|
+
const gameBestOf = bestof || 1;
|
|
231
|
+
gameState = rps.createInitialRPSState(gameBestOf);
|
|
232
|
+
|
|
233
|
+
await saveGameState(myHandle, 'rps', gameState, `Started new Rock Paper Scissors game (best of ${gameBestOf})!`);
|
|
234
|
+
|
|
235
|
+
const payload = createGamePayload('rps', gameState);
|
|
236
|
+
return {
|
|
237
|
+
display: `## New Rock Paper Scissors Game${gameBestOf > 1 ? ` (Best of ${gameBestOf})` : ''}\n\n${formatRPSPayload(payload)}\n\nUse \`vibe solo-game rps --move rock\` (or paper/scissors) to play`
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (action === 'status' || (!action && !move)) {
|
|
242
|
+
// Show current game state
|
|
243
|
+
const payload = createGamePayload('rps', gameState);
|
|
244
|
+
let displayText = `## Rock Paper Scissors${gameState.bestOf > 1 ? ` (Best of ${gameState.bestOf})` : ''}\n\n${formatRPSPayload(payload)}`;
|
|
245
|
+
|
|
246
|
+
if (gameState.gameOver) {
|
|
247
|
+
displayText += `\n\nUse \`vibe solo-game rps --action new\` to start a new game`;
|
|
248
|
+
} else {
|
|
249
|
+
displayText += `\n\nUse \`vibe solo-game rps --move rock\` (or paper/scissors) to make your move`;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return { display: displayText };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Handle moves (rock, paper, scissors can be action or move parameter)
|
|
256
|
+
const playerMove = move || action;
|
|
257
|
+
if (playerMove && ['rock', 'paper', 'scissors'].includes(playerMove.toLowerCase())) {
|
|
258
|
+
|
|
259
|
+
const result = rps.makeMove(gameState, playerMove);
|
|
260
|
+
|
|
261
|
+
if (result.error) {
|
|
262
|
+
return { display: `Error: ${result.error}` };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const newGameState = result.gameState;
|
|
266
|
+
|
|
267
|
+
// Save updated state
|
|
268
|
+
let message = `Played ${playerMove}`;
|
|
269
|
+
if (newGameState.gameOver) {
|
|
270
|
+
if (newGameState.winner === 'player') {
|
|
271
|
+
message += ' - You won the game! 🎉';
|
|
272
|
+
// Post to board for wins
|
|
273
|
+
postSoloGameResult(myHandle, 'Rock Paper Scissors', true, `${newGameState.playerScore}-${newGameState.opponentScore}`);
|
|
274
|
+
} else {
|
|
275
|
+
message += ' - You lost the game! 💀';
|
|
276
|
+
}
|
|
277
|
+
} else {
|
|
278
|
+
message += ` vs ${newGameState.lastRound.opponentChoice}`;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
await saveGameState(myHandle, 'rps', newGameState, message);
|
|
282
|
+
|
|
283
|
+
const payload = createGamePayload('rps', newGameState);
|
|
284
|
+
let displayText = `## Rock Paper Scissors${newGameState.bestOf > 1 ? ` (Best of ${newGameState.bestOf})` : ''}\n\n${formatRPSPayload(payload)}`;
|
|
285
|
+
|
|
286
|
+
if (newGameState.gameOver) {
|
|
287
|
+
displayText += `\n\nUse \`vibe solo-game rps --action new\` to start a new game`;
|
|
288
|
+
} else {
|
|
289
|
+
displayText += `\n\nUse \`vibe solo-game rps --move rock\` (or paper/scissors) for the next round`;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return { display: displayText };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return { display: 'Unknown action. Use: rock, paper, scissors, new, or status' };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (game === 'memory') {
|
|
299
|
+
// Get current game state
|
|
300
|
+
let gameState = await getCurrentGameState(myHandle, 'memory');
|
|
301
|
+
|
|
302
|
+
// Handle different actions
|
|
303
|
+
if (action === 'new' || !gameState) {
|
|
304
|
+
// Start new game
|
|
305
|
+
const gameDifficulty = difficulty || 'medium';
|
|
306
|
+
gameState = memory.createInitialMemoryState(gameDifficulty);
|
|
307
|
+
|
|
308
|
+
await saveGameState(myHandle, 'memory', gameState, `Started new ${gameDifficulty} memory pattern game!`);
|
|
309
|
+
|
|
310
|
+
const payload = createGamePayload('memory', gameState);
|
|
311
|
+
return {
|
|
312
|
+
display: `## New Memory Pattern Game (${gameDifficulty})\n\n${formatMemoryPayload(payload)}`
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (action === 'status' || (!action && !pattern)) {
|
|
317
|
+
// Show current game state
|
|
318
|
+
const payload = createGamePayload('memory', gameState);
|
|
319
|
+
let displayText = `## Memory Pattern Game\n\n${formatMemoryPayload(payload)}`;
|
|
320
|
+
|
|
321
|
+
if (gameState.gameOver) {
|
|
322
|
+
displayText += `\n\nUse \`vibe solo-game memory --action new\` to start a new game`;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return { display: displayText };
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (action === 'input') {
|
|
329
|
+
// Start input phase
|
|
330
|
+
const result = memory.startInput(gameState);
|
|
331
|
+
|
|
332
|
+
if (result.error) {
|
|
333
|
+
return { display: `Error: ${result.error}` };
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const newGameState = result.gameState;
|
|
337
|
+
|
|
338
|
+
await saveGameState(myHandle, 'memory', newGameState, 'Ready for input!');
|
|
339
|
+
|
|
340
|
+
const payload = createGamePayload('memory', newGameState);
|
|
341
|
+
return {
|
|
342
|
+
display: `## Memory Pattern Game\n\n${formatMemoryPayload(payload)}`
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (pattern) {
|
|
347
|
+
// Submit pattern guess
|
|
348
|
+
const result = memory.submitPattern(gameState, pattern);
|
|
349
|
+
|
|
350
|
+
if (result.error) {
|
|
351
|
+
return { display: `Error: ${result.error}` };
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const newGameState = result.gameState;
|
|
355
|
+
|
|
356
|
+
// Save updated state
|
|
357
|
+
let message = `Submitted pattern: ${pattern}`;
|
|
358
|
+
if (newGameState.gameOver) {
|
|
359
|
+
if (newGameState.won) {
|
|
360
|
+
message += ' - You won! 🎉';
|
|
361
|
+
// Post to board for wins
|
|
362
|
+
postSoloGameResult(myHandle, 'Memory Pattern', true, `Level ${newGameState.maxLevelReached}, Score ${newGameState.score}`);
|
|
363
|
+
} else {
|
|
364
|
+
message += ' - Game over! 🧠';
|
|
365
|
+
}
|
|
366
|
+
} else if (newGameState.lastResult === 'correct') {
|
|
367
|
+
message += ' - Correct! Next level!';
|
|
368
|
+
} else if (newGameState.lastResult === 'wrong') {
|
|
369
|
+
message += ' - Wrong! Try again!';
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
await saveGameState(myHandle, 'memory', newGameState, message);
|
|
373
|
+
|
|
374
|
+
const payload = createGamePayload('memory', newGameState);
|
|
375
|
+
let displayText = `## Memory Pattern Game\n\n${formatMemoryPayload(payload)}`;
|
|
376
|
+
|
|
377
|
+
if (newGameState.gameOver) {
|
|
378
|
+
displayText += `\n\nUse \`vibe solo-game memory --action new\` to start a new game`;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return { display: displayText };
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return { display: 'Unknown action. Use: new, status, input, or --pattern "🔴 🟡 🟢"' };
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return { display: 'Unknown game. Supported games: hangman, rps, memory' };
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
module.exports = { definition, handler };
|