CasinoGames/Blackjack/GAME_CENTER_PLAN.md

17 KiB
Raw Permalink Blame History

Game Center Integration - Blackjack

This document outlines the Game Center achievements for Blackjack and the game-specific integration steps.

Prerequisites

Complete CasinoKit/GAME_CENTER_PLAN.md implementation first (shared infrastructure)

Achievement Design Philosophy

Focus on learning milestones and skill demonstration, not bankroll/luck-based metrics.

Achievements celebrate:

  • 📚 Learning basic strategy
  • 🎓 Card counting practice
  • 🎯 Gameplay milestones
  • 💪 Persistence and mastery

Blackjack Achievements

🎓 Learning & Strategy Category

1. First Hand

  • ID: com.yourdomain.blackjack.first_hand
  • Description: Play your first hand of Blackjack
  • Progress: Complete on first hand
  • Points: 5
  • Icon: play.circle.fill
  • Trigger: After first finishRound() completes

2. Strategy Student

  • ID: com.yourdomain.blackjack.strategy_student
  • Description: Play 50 hands following perfect basic strategy
  • Progress: Incremental (0-50)
  • Points: 10
  • Icon: book.fill
  • Trigger: Each hand where player follows all hint recommendations
  • Implementation Note: Track in GameState when hint matches action taken

3. Strategy Master

  • ID: com.yourdomain.blackjack.strategy_master
  • Description: Play 100 hands following perfect basic strategy
  • Progress: Incremental (0-100)
  • Points: 25
  • Icon: graduationcap.fill
  • Trigger: Same as Strategy Student, extended goal

4. Card Counter

  • ID: com.yourdomain.blackjack.card_counter
  • Description: Play 25 hands using the Hi-Lo counting system
  • Progress: Incremental (0-25)
  • Points: 15
  • Icon: brain.head.profile
  • Trigger: When settings.showCount is enabled and hand completes
  • Implementation Note: Must have counting enabled in settings

5. True Count Master

  • ID: com.yourdomain.blackjack.true_count_master
  • Description: Make 10 correct betting decisions based on true count
  • Progress: Incremental (0-10)
  • Points: 20
  • Icon: chart.line.uptrend.xyaxis
  • Trigger: When player increases bet with positive true count (+2 or higher)
  • Implementation Note: Track bet increases that align with count recommendations

🎯 Gameplay Milestones Category

6. Natural Talent

  • ID: com.yourdomain.blackjack.natural_10
  • Description: Get 10 Blackjacks (natural 21)
  • Progress: Incremental (0-10)
  • Points: 10
  • Icon: star.fill
  • Trigger: When player hand is natural blackjack

7. Natural Legend

  • ID: com.yourdomain.blackjack.natural_50
  • Description: Get 50 Blackjacks
  • Progress: Incremental (0-50)
  • Points: 25
  • Icon: star.circle.fill
  • Trigger: When player hand is natural blackjack (extended)

8. Split Decision

  • ID: com.yourdomain.blackjack.split_wins_10
  • Description: Win with split hands 10 times
  • Progress: Incremental (0-10)
  • Points: 10
  • Icon: rectangle.split.2x1.fill
  • Trigger: When a split hand wins against dealer

9. Double Down Dynamo

  • ID: com.yourdomain.blackjack.double_wins_15
  • Description: Win 15 hands after doubling down
  • Progress: Incremental (0-15)
  • Points: 15
  • Icon: arrow.down.circle.fill
  • Trigger: When player wins a hand after doubling down

10. Insurance Agent

  • ID: com.yourdomain.blackjack.insurance_wins_5
  • Description: Win insurance bet 5 times
  • Progress: Incremental (0-5)
  • Points: 10
  • Icon: shield.checkered
  • Trigger: When dealer has blackjack and player took insurance

💪 Persistence & Mastery Category

11. Rookie

  • ID: com.yourdomain.blackjack.hands_100
  • Description: Play 100 total hands
  • Progress: Incremental (0-100)
  • Points: 10
  • Icon: person.fill
  • Trigger: After each hand completes

12. Regular

  • ID: com.yourdomain.blackjack.hands_500
  • Description: Play 500 total hands
  • Progress: Incremental (0-500)
  • Points: 25
  • Icon: person.2.fill
  • Trigger: After each hand completes

13. Veteran

  • ID: com.yourdomain.blackjack.hands_1000
  • Description: Play 1,000 total hands
  • Progress: Incremental (0-1000)
  • Points: 50
  • Icon: person.3.fill
  • Trigger: After each hand completes

14. Comeback Kid

  • ID: com.yourdomain.blackjack.comeback
  • Description: Recover from under $100 to $10,000 in a single session
  • Progress: Complete when achieved
  • Points: 25
  • Icon: arrow.up.right.circle.fill
  • Trigger: When balance reaches $10k after being below $100 in same session
  • Implementation Note: Track session low point

15. Perfect Pair Player

  • ID: com.yourdomain.blackjack.perfect_pairs_5
  • Description: Win Perfect Pairs side bet 5 times
  • Progress: Incremental (0-5)
  • Points: 10
  • Icon: suit.heart.fill
  • Trigger: When Perfect Pairs side bet wins

16. 21+3 Champion

  • ID: com.yourdomain.blackjack.twentyone_plus_three_5
  • Description: Win 21+3 side bet 5 times
  • Progress: Incremental (0-5)
  • Points: 10
  • Icon: suit.diamond.fill
  • Trigger: When 21+3 side bet wins

🏆 Elite Category

17. Side Bet Specialist

  • ID: com.yourdomain.blackjack.side_bet_wins_25
  • Description: Win any side bet 25 times total
  • Progress: Incremental (0-25)
  • Points: 25
  • Icon: plus.circle.fill
  • Trigger: Any time a side bet wins (Perfect Pairs or 21+3)

18. Rule Breaker (Hidden Achievement)

  • ID: com.yourdomain.blackjack.all_rule_variations
  • Description: Play at least 10 hands with each rule variation
  • Progress: Incremental (0-40, 10 per variation × 4 variations)
  • Points: 15
  • Icon: gearshape.2.fill
  • Trigger: Track which rule sets have been played
  • Implementation Note: Vegas Strip, Atlantic City, European, Custom (10 hands each)

Implementation Steps

1. Define Achievement Enum

File: Blackjack/Blackjack/Models/BlackjackAchievement.swift (new file)

import CasinoKit
import GameKit

enum BlackjackAchievement: String, AchievementDefinition {
    case firstHand = "first_hand"
    case strategyStudent = "strategy_student"
    case strategyMaster = "strategy_master"
    case cardCounter = "card_counter"
    case trueCountMaster = "true_count_master"
    case natural10 = "natural_10"
    case natural50 = "natural_50"
    case splitWins10 = "split_wins_10"
    case doubleWins15 = "double_wins_15"
    case insuranceWins5 = "insurance_wins_5"
    case hands100 = "hands_100"
    case hands500 = "hands_500"
    case hands1000 = "hands_1000"
    case comeback = "comeback"
    case perfectPairs5 = "perfect_pairs_5"
    case twentyOnePlusThree5 = "twentyone_plus_three_5"
    case sideBetWins25 = "side_bet_wins_25"
    case allRuleVariations = "all_rule_variations"
    
    var identifier: String {
        "com.yourdomain.blackjack.\(rawValue)"
    }
    
    var title: String {
        switch self {
        case .firstHand: return String(localized: "First Hand")
        case .strategyStudent: return String(localized: "Strategy Student")
        case .strategyMaster: return String(localized: "Strategy Master")
        case .cardCounter: return String(localized: "Card Counter")
        case .trueCountMaster: return String(localized: "True Count Master")
        case .natural10: return String(localized: "Natural Talent")
        case .natural50: return String(localized: "Natural Legend")
        case .splitWins10: return String(localized: "Split Decision")
        case .doubleWins15: return String(localized: "Double Down Dynamo")
        case .insuranceWins5: return String(localized: "Insurance Agent")
        case .hands100: return String(localized: "Rookie")
        case .hands500: return String(localized: "Regular")
        case .hands1000: return String(localized: "Veteran")
        case .comeback: return String(localized: "Comeback Kid")
        case .perfectPairs5: return String(localized: "Perfect Pair Player")
        case .twentyOnePlusThree5: return String(localized: "21+3 Champion")
        case .sideBetWins25: return String(localized: "Side Bet Specialist")
        case .allRuleVariations: return String(localized: "Rule Breaker")
        }
    }
    
    var description: String {
        // Full descriptions for each achievement
    }
    
    var maxProgress: Int {
        switch self {
        case .firstHand, .comeback: return 1
        case .insuranceWins5, .perfectPairs5, .twentyOnePlusThree5: return 5
        case .splitWins10, .natural10: return 10
        case .doubleWins15: return 15
        case .cardCounter, .sideBetWins25, .strategyMaster: return 25
        case .strategyStudent, .natural50: return 50
        case .hands100: return 100
        case .hands500: return 500
        case .hands1000: return 1000
        case .trueCountMaster: return 10
        case .allRuleVariations: return 40
        }
    }
    
    var isIncremental: Bool {
        self != .firstHand && self != .comeback
    }
    
    var iconName: String {
        switch self {
        case .firstHand: return "play.circle.fill"
        case .strategyStudent: return "book.fill"
        case .strategyMaster: return "graduationcap.fill"
        case .cardCounter: return "brain.head.profile"
        case .trueCountMaster: return "chart.line.uptrend.xyaxis"
        case .natural10: return "star.fill"
        case .natural50: return "star.circle.fill"
        case .splitWins10: return "rectangle.split.2x1.fill"
        case .doubleWins15: return "arrow.down.circle.fill"
        case .insuranceWins5: return "shield.checkered"
        case .hands100: return "person.fill"
        case .hands500: return "person.2.fill"
        case .hands1000: return "person.3.fill"
        case .comeback: return "arrow.up.right.circle.fill"
        case .perfectPairs5: return "suit.heart.fill"
        case .twentyOnePlusThree5: return "suit.diamond.fill"
        case .sideBetWins25: return "plus.circle.fill"
        case .allRuleVariations: return "gearshape.2.fill"
        }
    }
}

2. Add Achievement Tracker to GameState

File: Blackjack/Blackjack/Engine/GameState.swift

import CasinoKit

@MainActor
@Observable
class GameState {
    // ... existing properties ...
    
    // NEW: Achievement tracking
    private(set) var achievementTracker: AchievementTracker<BlackjackAchievement>
    
    // Track session-specific metrics for achievements
    private var sessionLowBalance: Int = 0
    private var handsPlayedThisSession = 0
    private var lastActionWasStrategyOptimal = false
    
    init() {
        // ... existing init ...
        
        self.achievementTracker = AchievementTracker<BlackjackAchievement>()
        self.sessionLowBalance = balance
    }
    
    // NEW: Achievement checking methods
    func checkAchievements(after action: GameAction) {
        // Called after each game action
        // Check relevant achievements based on action type
    }
    
    private func updateSessionTracking() {
        if balance < sessionLowBalance {
            sessionLowBalance = balance
        }
        
        // Check comeback achievement
        if sessionLowBalance < 100 && balance >= 10_000 {
            achievementTracker.complete(.comeback)
        }
    }
}

3. Add Achievement Triggers

Add achievement checks throughout game logic:

In BlackjackEngine.swift or GameState.swift:

// After dealing initial cards
if playerHand.isBlackjack {
    achievementTracker.increment(.natural10)
    achievementTracker.increment(.natural50)
}

// After completing a hand
func finishRound() {
    // ... existing logic ...
    
    // First hand achievement
    if totalHandsPlayed == 1 {
        achievementTracker.complete(.firstHand)
    }
    
    // Persistence achievements
    achievementTracker.increment(.hands100)
    achievementTracker.increment(.hands500)
    achievementTracker.increment(.hands1000)
    
    // Check if strategy was followed
    if lastActionWasStrategyOptimal {
        achievementTracker.increment(.strategyStudent)
        achievementTracker.increment(.strategyMaster)
    }
    
    // Card counting achievements
    if settings.showCount {
        achievementTracker.increment(.cardCounter)
        
        // Check if bet was adjusted based on count
        if betWasIncreasedWithPositiveCount {
            achievementTracker.increment(.trueCountMaster)
        }
    }
    
    updateSessionTracking()
}

// After winning with split
func checkSplitWin() {
    if handWasSplit && playerWon {
        achievementTracker.increment(.splitWins10)
    }
}

// After winning with double down
func checkDoubleWin() {
    if playerDoubledDown && playerWon {
        achievementTracker.increment(.doubleWins15)
    }
}

// After insurance win
func checkInsuranceWin() {
    if insuranceBetWon {
        achievementTracker.increment(.insuranceWins5)
    }
}

// After side bet wins
func checkSideBetWins() {
    if perfectPairsBetWon {
        achievementTracker.increment(.perfectPairs5)
        achievementTracker.increment(.sideBetWins25)
    }
    
    if twentyOnePlusThreeBetWon {
        achievementTracker.increment(.twentyOnePlusThree5)
        achievementTracker.increment(.sideBetWins25)
    }
}

4. Add Game Center to Settings

File: Blackjack/Blackjack/Views/Sheets/SettingsView.swift

import CasinoKit

struct SettingsView: View {
    // ... existing code ...
    
    var body: some View {
        SheetContainerView(title: String(localized: "Settings")) {
            // ... existing sections ...
            
            // NEW: Game Center section
            GameCenterSettingsSection()
            
        } onDone: {
            dismiss()
        }
    }
}

5. Optional: Add Game Center Access Point

File: Blackjack/Blackjack/Views/Game/GameTableView.swift

Add to top bar or as floating overlay:

TopBarView(
    balance: state.balance,
    // ... existing parameters ...
    leadingButtons: [
        TopBarButton(
            icon: "gamecontroller.fill",
            accessibilityLabel: "Game Center"
        ) {
            GameCenterManager.shared.showGameCenterDashboard()
        }
    ]
)

6. Initialize Game Center on App Launch

File: Blackjack/Blackjack/BlackjackApp.swift

import CasinoKit

@main
struct BlackjackApp: App {
    init() {
        // Authenticate with Game Center silently
        Task {
            await GameCenterManager.shared.authenticate()
        }
    }
    
    // ... rest of app ...
}

7. Add Localized Strings

File: Blackjack/Blackjack/Resources/Localizable.xcstrings

Add all achievement titles, descriptions, and Game Center UI strings.

App Store Connect Configuration

For Each Achievement:

  1. Log into App Store Connect
  2. Select Blackjack app
  3. Go to Game Center → Achievements
  4. Click "+" to add achievement
  5. Configure:
    • Reference Name: (internal only, e.g., "Strategy Student")
    • Achievement ID: Must match enum identifier (e.g., com.yourdomain.blackjack.strategy_student)
    • Point Value: As specified above
    • Hidden: Set to "Yes" for hidden achievements (Rule Breaker)
    • Achievable More Than Once: No for all
    • Pre-iOS 14 Gamers: Leave unchecked
    • Localization: Add EN, ES-MX, FR-CA with titles/descriptions
    • Images: Upload 512x512 and 1024x1024 versions

Achievement Icon Assets

Create icons matching the SF Symbols specified in the achievement enum. Use your app's color scheme (golds, blues, casino theme).

Testing Checklist

  • All achievements can be triggered in game
  • Incremental achievements show progress correctly
  • Achievements appear in Game Center dashboard
  • Achievements work offline (queue and submit later)
  • Achievement tracking persists across app launches
  • Localization works for all three languages
  • VoiceOver announces achievement unlocks
  • Settings section shows correct Game Center status
  • Strategy-based achievements verify correct play
  • Card counting achievements only trigger when enabled

Edge Cases to Handle

  1. Player resets game mid-session - Session achievements (comeback) should reset
  2. Player changes rule variations - Track separately for "Rule Breaker"
  3. Player disables hints - Strategy achievements still trackable via engine logic
  4. Offline play - Queue achievements, submit when online
  5. Multiple devices - Game Center syncs achievement progress automatically

Analytics to Track (Optional)

Consider adding local analytics to understand achievement engagement:

  • Which achievements are earned most often?
  • Average time to complete each achievement
  • Percentage of players who enable card counting (for targeted education)

Future Enhancements

  • Achievement notifications - Show toast when unlocked (use CasinoKit's AchievementToast)
  • Progress tracking UI - Show achievement progress in stats view
  • Suggested next achievement - Guide players toward specific goals

Summary

  • 18 total achievements
  • Focus on learning and skill, not luck/bankroll
  • Incremental progress for most achievements
  • Hidden achievement for exploring all rule variations
  • Integration with existing GameState and statistics
  • No code duplication (uses CasinoKit infrastructure)

Estimated Integration Time: 2-3 hours after CasinoKit infrastructure is complete.


See CasinoKit/GAME_CENTER_PLAN.md for shared infrastructure implementation details.