Agent skill
quiz-game-mechanics
Implement quiz game logic including game creation, player turn management, score calculation, answer validation, and game completion. Use when building game flows, turn-based mechanics, and scoring algorithms.
Install this agent skill to your Project
npx add-skill https://github.com/violabg/dev-quiz-battle/tree/main/skills/quiz-game-mechanics
Metadata
Additional technical details for this skill
- author
- dev-quiz-battle
- version
- 1.0
SKILL.md
Quiz Game Mechanics
This skill covers the core game logic and mechanics for dev-quiz-battle.
Step-by-step instructions
1. Game Creation
Create a game with initial state:
export const createGame = mutation({
args: {
creatorId: v.id("users"),
language: v.string(),
maxRounds: v.number(),
},
handler: async (ctx, args) => {
const code = generateUniqueGameCode(6);
const gameId = await ctx.db.insert("games", {
code,
creatorId: args.creatorId,
status: "waiting",
language: args.language,
players: [args.creatorId],
currentRound: 0,
maxRounds: args.maxRounds,
createdAt: Date.now(),
});
return { gameId, code };
},
});
2. Player Management
Add and remove players from game:
export const joinGame = mutation({
args: { gameCode: v.string(), playerId: v.id("users") },
handler: async (ctx, args) => {
const game = await ctx.db
.query("games")
.filter((q) => q.eq(q.field("code"), args.gameCode))
.first();
if (!game) throw new Error("Game not found");
if (game.status !== "waiting") throw new Error("Game already started");
await ctx.db.patch(game._id, {
players: [...game.players, args.playerId],
});
return game._id;
},
});
3. Turn Management
Handle player turns:
export const startNextRound = mutation({
args: { gameId: v.id("games") },
handler: async (ctx, args) => {
const game = await ctx.db.get(args.gameId);
if (!game) throw new Error("Game not found");
const nextRound = game.currentRound + 1;
if (nextRound > game.maxRounds) {
// Game is finished
await ctx.db.patch(args.gameId, { status: "finished" });
return { status: "finished" };
}
// Generate questions for this round
const questions = await generateQuestionsForRound(
game.language,
game.players.length
);
await ctx.db.patch(args.gameId, {
currentRound: nextRound,
status: "in-progress",
currentQuestions: questions.map((q) => q._id),
});
return { status: "in-progress", round: nextRound };
},
});
4. Score Calculation
Calculate points based on correctness and speed:
const calculateScore = (
isCorrect: boolean,
timeMs: number,
difficulty: "easy" | "medium" | "hard"
): number => {
if (!isCorrect) return 0;
const baseScore = { easy: 10, medium: 20, hard: 30 }[difficulty];
const timeBonus = Math.max(0, 30 - Math.floor(timeMs / 1000));
return baseScore + timeBonus;
};
export const submitAnswer = mutation({
args: {
gameId: v.id("games"),
playerId: v.id("users"),
questionId: v.id("questions"),
answer: v.string(),
timeMs: v.number(),
},
handler: async (ctx, args) => {
const question = await ctx.db.get(args.questionId);
if (!question) throw new Error("Question not found");
const isCorrect = question.correctAnswer === args.answer;
const score = calculateScore(isCorrect, args.timeMs, question.difficulty);
const answerId = await ctx.db.insert("answers", {
gameId: args.gameId,
playerId: args.playerId,
questionId: args.questionId,
answer: args.answer,
isCorrect,
timeMs: args.timeMs,
scoreEarned: score,
submittedAt: Date.now(),
});
return { answerId, isCorrect, scoreEarned: score };
},
});
5. Game Completion
Handle game ending and winner determination:
export const completeGame = mutation({
args: { gameId: v.id("games") },
handler: async (ctx, args) => {
const game = await ctx.db.get(args.gameId);
if (!game) throw new Error("Game not found");
// Get all answers for this game
const answers = await ctx.db
.query("answers")
.filter((q) => q.eq(q.field("gameId"), args.gameId))
.collect();
// Calculate final scores
const playerScores = new Map<string, number>();
answers.forEach((answer) => {
const current = playerScores.get(answer.playerId) || 0;
playerScores.set(answer.playerId, current + answer.scoreEarned);
});
const winner = Array.from(playerScores.entries()).sort(
([, a], [, b]) => b - a
)[0];
// Update user stats
await ctx.db.patch(game._id, {
status: "finished",
winnerId: winner?.[0],
finalScores: Object.fromEntries(playerScores),
});
return {
winnerId: winner?.[0],
finalScores: Object.fromEntries(playerScores),
};
},
});
Common Edge Cases
- Simultaneous submissions: Last submission wins
- Disconnected players: Mark as inactive, don't count answers
- Time validation: Reject answers submitted after round timeout
- Language validation: Ensure selected language matches available questions
- Tie handling: Multiple players with same score
Scoring Rules
- Easy questions: 10 points base + time bonus
- Medium questions: 20 points base + time bonus
- Hard questions: 30 points base + time bonus
- Time bonus: +1 point per second remaining (max 30 seconds)
- Incorrect answers: 0 points
See Game Balance Reference for tuning parameters.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
next-best-practices
Next.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling
vercel-react-best-practices
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
shadcn
Manages shadcn components and projects — adding, searching, fixing, debugging, styling, and composing UI. Provides project context, component docs, and usage examples. Applies when working with shadcn/ui, component registries, presets, --preset codes, or any project with a components.json file. Also triggers for "shadcn init", "create an app with --preset", or "switch to --preset".
frontend-design
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
convex
Umbrella skill for all Convex development patterns. Routes to specific skills like convex-functions, convex-realtime, convex-agents, etc.
tailwind-theme-styling
Style the dev-quiz-battle app using Tailwind CSS v4 with OKLCH colors, dark mode support, and modern design patterns. Use when creating responsive layouts, applying themes, and implementing visual components.
Didn't find tool you were looking for?