Agent skill
convex-game-management
Manage game lifecycle, player turns, round rotation, scoring, and game state transitions. Use when implementing game creation, turn management, score updates, and game completion flows in PictionAI.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/convex-game-management
Metadata
Additional technical details for this skill
- author
- PictionAI
- category
- backend
- frameworks
- Convex, Next.js
SKILL.md
Convex Game Management
Overview
This skill handles the complete game lifecycle for PictionAI's multiplayer Pictionary game, including game creation, player management, turn-based rotation, atomic turn completion with scoring, and game state transitions.
Core Concepts
Game States
- waiting - Game created, players joining in lobby
- started - Game in progress, turns rotating
- finished - All rounds complete, winner determined
Turn States
- drawing - Active turn, timer running (60-120 seconds)
- completed - Turn finished with correct guess
- time_up - Timer expired, no points awarded
Atomic Turn System
Turns are completed atomically to ensure data consistency:
- Start Turn: Drawer calls
startNewTurnmutation - Draw & Guess Phase: Real-time canvas sync, players submit guesses
- Turn Completion: Three atomic scenarios:
- ✅ Correct guess → Both guesser and drawer earn points
- 🏆 Manual winner selection → Drawer selects winner from guessers
- ⏱️ Time up → No points, proceed to next turn
- Score Updates: Dual scoring system (guesser time bonus + drawer base score)
- Next Turn: Auto round-robin rotation to next player
Scoring System
Guess Scoring (Correct Answer)
- Guesser: Base 50 points + time bonus (50 - elapsed_seconds, min 5 points)
- Drawer: 25% of guesser's score, minimum 10 points
Drawer Scoring (Manual Winner)
- Selected Guesser: 30 points
- Drawer: 25 points
Key Mutations
startNewTurn
Start a new drawing turn, assign card, initialize timer.
mutation startNewTurn {
args: {
game_id: Id<"games">
}
// Returns: {
// turn_id: Id<"turns">,
// card: { word: string, category: string },
// drawer_id: Id<"users">,
// time_limit: number
// }
}
submitGuessAndCompleteTurn
Submit a guess and complete the turn with atomic scoring.
mutation submitGuessAndCompleteTurn {
args: {
game_id: Id<"games">,
turn_id: Id<"turns">,
guesser_id: Id<"users">,
guess: string,
elapsed_time: number,
is_correct?: boolean
}
// Handles three scenarios atomically:
// 1. Correct guess → Award points to both
// 2. Manual selection → Drawer chooses winner
// 3. Time up → Skip to next turn
}
selectWinner (Manual Selection)
Drawer selects a guesser as the winner when time expires.
mutation selectWinner {
args: {
turn_id: Id<"turns">,
selected_guesser_id: Id<"users">
}
// Awards 30 points to guesser, 25 to drawer
}
Key Queries
getGame
Fetch complete game state with players, current turn, scores.
query getGame {
args: { game_id: Id<"games"> }
// Returns full game with nested players, turns, scores
}
getGameTurns
Get all turns in a game with guesses and results.
query getGameTurns {
args: { game_id: Id<"games"> }
// Returns array of turns with scoring details
}
React Integration
// Start a new turn
const startTurn = useMutation(api.mutations.game.startNewTurn);
await startTurn({ game_id: gameId });
// Submit guess and complete turn
const submitGuess = useMutation(api.mutations.game.submitGuessAndCompleteTurn);
await submitGuess({
game_id: gameId,
turn_id: turnId,
guesser_id: userId,
guess: "elephant",
elapsed_time: 45,
});
// Fetch game state
const game = useQuery(api.queries.games.getGame, { game_id: gameId });
Database Schema References
// Games table
games: defineTable({
code: v.string(), // Unique game code
creator_id: v.id("users"),
players: v.array(
v.object({
user_id: v.id("users"),
score: v.number(),
is_drawer: v.boolean(),
})
),
state: v.union(
v.literal("waiting"),
v.literal("started"),
v.literal("finished")
),
current_turn_index: v.number(),
created_at: v.optional(v.number()),
round_count: v.number(),
});
// Turns table
turns: defineTable({
game_id: v.id("games"),
drawer_id: v.id("users"),
card_id: v.id("cards"),
state: v.union(
v.literal("drawing"),
v.literal("completed"),
v.literal("time_up")
),
timer_started_at: v.number(),
time_limit: v.number(),
correct_guesser_id: v.optional(v.id("users")),
guesses: v.array(
v.object({
guesser_id: v.id("users"),
guess: v.string(),
timestamp: v.number(),
is_correct: v.optional(v.boolean()),
})
),
});
Common Patterns
Monitor active turn
const game = useQuery(api.queries.games.getGame, { game_id });
const currentTurn = game?.turns[game.current_turn_index];
const isMyTurn = currentTurn?.drawer_id === userId;
Handle turn completion
// When drawer completes turn with guess result
const completeWithCorrect = useMutation(
api.mutations.game.submitGuessAndCompleteTurn
);
await completeWithCorrect({
game_id: gameId,
turn_id: turnId,
guesser_id: guesserId,
guess: "elephant",
elapsed_time: 30,
is_correct: true,
});
Automatic next turn
The mutation automatically:
- Rotates drawer (round-robin through players)
- Assigns new card
- Starts timer
- Updates game state
Edge Cases
- Multiple guesses per player: Allowed, only latest is scored
- Guess submitted after timer: System checks elapsed time on server
- Late guess arrival: Real-time subscription updates guess feed
- Manual selection ambiguity: Drawer must explicitly select one winner
- Game with 2 players: Drawer rotation still works with round-robin
See Also
- TURN_MANAGEMENT_ANALYSIS.md - Detailed atomic turn analysis
convex/mutations/game.ts- Complete mutation implementationscomponents/game/game-board.tsx- UI integration
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?