# 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) ```swift 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` ```swift import CasinoKit @MainActor @Observable class GameState { // ... existing properties ... // NEW: Achievement tracking private(set) var achievementTracker: AchievementTracker // 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() 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`:** ```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` ```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: ```swift 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` ```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.*