You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
12 KiB
12 KiB
Know Foolery - Game Mechanics Documentation
Overview
Know Foolery is a quiz game where players answer questions to earn points within a time-limited session. The game emphasizes strategic thinking through its hint system and attempt limitations.
Core Game Flow
1. Game Session Initialization
Player Input: Name → Session Creation → Question Selection → Game Start
Process:
- Player enters their name (required)
- System creates new game session
- System randomly selects first question
- 30-minute timer starts
- Game begins with question display
Validation:
- Player name: 2-50 characters, alphanumeric + spaces
- Session uniqueness: One active session per player
- Timer initialization: Server-side timestamp
2. Question Presentation
Question Structure:
interface Question {
id: string
theme: string // e.g., "Geography", "History", "Science"
text: string // The actual question
answer: string // Correct answer (case-insensitive)
hint: string // Optional hint text
difficulty?: number // Future enhancement
}
Display Format:
┌─────────────────────────────────────┐
│ Theme: Geography ⏱️ 28:45 │
├─────────────────────────────────────┤
│ │
│ What is the capital of France? │
│ │
│ [Your answer here... ] 💡 │
│ │
│ Attempts remaining: 3/3 │
│ Current score: 4 points │
└─────────────────────────────────────┘
3. Answer Submission Process
Player Actions:
- Direct Answer: Submit answer without hint
- Request Hint: View hint before answering
- Skip Question: Move to next question (future enhancement)
Answer Validation:
// Server-side validation logic
func ValidateAnswer(userAnswer, correctAnswer string) bool {
// Normalize both answers
user := strings.ToLower(strings.TrimSpace(userAnswer))
correct := strings.ToLower(strings.TrimSpace(correctAnswer))
// Exact match
if user == correct {
return true
}
// Fuzzy matching (future enhancement)
similarity := calculateSimilarity(user, correct)
return similarity > 0.85
}
Scoring System
Point Values
- Correct without hint: 2 points
- Correct with hint: 1 point
- Incorrect answer: 0 points
- Session timeout: 0 points for remaining questions
Scoring Logic
type AttemptResult struct {
IsCorrect bool
UsedHint bool
AttemptNum int // 1, 2, or 3
}
func CalculateScore(result AttemptResult) int {
if !result.IsCorrect {
return 0
}
if result.UsedHint {
return 1 // Reduced score for using hint
}
return 2 // Full score for direct correct answer
}
Score Tracking
type GameSession struct {
PlayerName string
TotalScore int
QuestionsAsked int
QuestionsCorrect int
HintsUsed int
StartTime time.Time
EndTime *time.Time
IsActive bool
}
Attempt System
Attempt Rules
- Maximum Attempts: 3 per question
- Attempt Tracking: Server-side validation
- Attempt Consequences:
- Attempt 1-3: Normal scoring if correct
- After 3 failed attempts: Move to next question automatically
Attempt Flow
type QuestionAttempt struct {
SessionID string
QuestionID string
AttemptNum int // 1, 2, or 3
Answer string
IsCorrect bool
UsedHint bool
Timestamp time.Time
}
func ProcessAttempt(sessionID, questionID, answer string) AttemptResult {
// 1. Validate session is active
// 2. Check attempts remaining
// 3. Validate answer
// 4. Update score if correct
// 5. Move to next question if needed
}
Hint System
Hint Mechanics
- Availability: One hint per question
- Timing: Can be requested before any attempt
- Impact: Reduces maximum score from 2 to 1 points
- Content: Provides helpful clue without giving away answer
Hint Implementation
interface HintRequest {
sessionId: string
questionId: string
}
interface HintResponse {
hint: string
scoreImpact: string // "Using this hint will reduce your score to 1 point"
attemptsRemaining: number
}
Hint Examples
const hintExamples = {
question: "What is the capital of France?",
hint: "This city is famous for the Eiffel Tower and is located on the Seine River.",
question: "Who painted the Mona Lisa?",
hint: "This Italian Renaissance artist was also an inventor and scientist.",
question: "What is the largest planet in our solar system?",
hint: "This gas giant is named after the king of the Roman gods."
}
Time Management
Session Timer
- Duration: 30 minutes maximum per session
- Display: Real-time countdown timer
- Warnings: Visual alerts at 5 minutes and 1 minute remaining
- Timeout: Automatic session termination when time expires
Timer Implementation
type SessionTimer struct {
SessionID string
StartTime time.Time
Duration time.Duration // 30 minutes
WarningsSent map[int]bool // Track warnings sent
}
func (t *SessionTimer) TimeRemaining() time.Duration {
elapsed := time.Since(t.StartTime)
remaining := t.Duration - elapsed
if remaining < 0 {
return 0
}
return remaining
}
func (t *SessionTimer) IsExpired() bool {
return t.TimeRemaining() == 0
}
Timer Events
interface TimerEvent {
type: 'warning' | 'timeout'
timeRemaining: number // seconds
message: string
}
// Timer warnings
const timerWarnings = [
{ at: 300, message: "5 minutes remaining!" }, // 5 minutes
{ at: 60, message: "1 minute remaining!" }, // 1 minute
{ at: 10, message: "10 seconds left!" } // 10 seconds
]
Question Selection
Random Selection Algorithm
func SelectRandomQuestion(sessionID string, excludeAnswered bool) (*Question, error) {
var questions []Question
query := db.Question.Query()
if excludeAnswered {
// Exclude questions already answered in this session
answeredIDs := getAnsweredQuestions(sessionID)
query = query.Where(question.IDNotIn(answeredIDs...))
}
questions, err := query.All(ctx)
if err != nil {
return nil, err
}
if len(questions) == 0 {
return nil, errors.New("no more questions available")
}
// Random selection
randomIndex := rand.Intn(len(questions))
return &questions[randomIndex], nil
}
Question Difficulty (Future Enhancement)
type DifficultyLevel int
const (
Easy DifficultyLevel = iota + 1
Medium
Hard
)
// Adaptive difficulty based on player performance
func SelectQuestionByDifficulty(sessionID string, targetDifficulty DifficultyLevel) (*Question, error) {
// Implementation for adaptive difficulty
// Consider player's success rate, current score, etc.
}
Leaderboard System
Leaderboard Calculation
type LeaderboardEntry struct {
PlayerName string
Score int
QuestionsAnswered int
SuccessRate float64 // Percentage of correct answers
SessionDuration time.Duration
CompletedAt time.Time
}
func CalculateLeaderboard() ([]LeaderboardEntry, error) {
sessions := getCompletedSessions()
entries := make([]LeaderboardEntry, 0, len(sessions))
for _, session := range sessions {
entry := LeaderboardEntry{
PlayerName: session.PlayerName,
Score: session.TotalScore,
QuestionsAnswered: session.QuestionsAsked,
SuccessRate: float64(session.QuestionsCorrect) / float64(session.QuestionsAsked) * 100,
SessionDuration: session.EndTime.Sub(session.StartTime),
CompletedAt: *session.EndTime,
}
entries = append(entries, entry)
}
// Sort by score (descending), then by completion time (ascending)
sort.Slice(entries, func(i, j int) bool {
if entries[i].Score == entries[j].Score {
return entries[i].CompletedAt.Before(entries[j].CompletedAt)
}
return entries[i].Score > entries[j].Score
})
// Return top 10
if len(entries) > 10 {
entries = entries[:10]
}
return entries, nil
}
Leaderboard Display
🏆 LEADERBOARD
Rank | Player | Score | Questions | Success Rate | Duration
-----|-----------|-------|-----------|--------------|----------
1 | Alice | 24 | 14 | 86% | 28m
2 | Bob | 22 | 13 | 85% | 25m
3 | Charlie | 20 | 12 | 83% | 30m
4 | Diana | 18 | 11 | 82% | 22m
5 | Eve | 16 | 10 | 80% | 27m
Game State Management
Session States
type SessionState int
const (
SessionCreated SessionState = iota
SessionActive
SessionPaused // Future enhancement
SessionCompleted
SessionTimedOut
SessionAbandoned
)
type GameSession struct {
ID string
PlayerName string
State SessionState
CurrentQuestion *Question
Score int
// ... other fields
}
State Transitions
Created → Active → {Completed, TimedOut, Abandoned}
↓
Paused → Active (future enhancement)
Anti-Cheating Measures
Server-Side Validation
type SecurityCheck struct {
SessionID string
QuestionID string
ExpectedAnswer string
SubmittedAnswer string
TimestampSubmit time.Time
TimestampShow time.Time
IsValid bool
Reason string
}
func ValidateSubmission(check SecurityCheck) bool {
// 1. Check minimum time between question show and answer submit
minTime := 2 * time.Second
if check.TimestampSubmit.Sub(check.TimestampShow) < minTime {
check.Reason = "Answer submitted too quickly"
return false
}
// 2. Validate session state
session := getSession(check.SessionID)
if session.State != SessionActive {
check.Reason = "Invalid session state"
return false
}
// 3. Check if question belongs to session
if session.CurrentQuestion.ID != check.QuestionID {
check.Reason = "Question mismatch"
return false
}
return true
}
Client-Side Integrity
// Prevent common cheating attempts
class GameIntegrity {
private questionStartTime: number = 0
onQuestionDisplayed() {
this.questionStartTime = Date.now()
// Disable browser dev tools (basic deterrent)
this.disableDevTools()
// Prevent copy-paste in answer input
this.disableCopyPaste()
}
onAnswerSubmit(answer: string) {
const timeTaken = Date.now() - this.questionStartTime
// Include timing in submission for server validation
return {
answer,
timeTaken,
timestamp: Date.now()
}
}
private disableDevTools() {
// Basic dev tools detection (not foolproof)
const devtools = {
open: false,
orientation: null
}
const threshold = 160
setInterval(() => {
if (window.outerHeight - window.innerHeight > threshold ||
window.outerWidth - window.innerWidth > threshold) {
console.warn('Developer tools detected')
// Log security event
}
}, 500)
}
}
Future Enhancements
Planned Features
- Question Categories: Filter questions by subject
- Difficulty Progression: Adaptive difficulty based on performance
- Multiplayer Mode: Real-time competition between players
- Daily Challenges: Special themed question sets
- Achievement System: Badges and milestones
- Question Contributions: Player-submitted questions
Scoring Enhancements
- Time Bonus: Extra points for quick correct answers
- Streak Bonus: Consecutive correct answers bonus
- Difficulty Multiplier: Higher points for harder questions
- Perfect Game Bonus: Bonus for 100% correct rate
This game mechanics documentation ensures consistent implementation across all platforms and provides clear guidelines for future enhancements.