# Game Center Integration - Baccarat This document outlines the Game Center achievements for Baccarat and the game-specific integration steps. ## Prerequisites ✅ Complete `CasinoKit/GAME_CENTER_PLAN.md` implementation first (shared infrastructure) ## Achievement Design Philosophy Focus on **gameplay milestones**, **pattern recognition**, and **understanding Baccarat strategy**, not pure luck or bankroll metrics. Achievements celebrate: - 🎲 Understanding Baccarat rules and betting - 📊 Pattern recognition (road maps) - 💎 High-stakes play (earned through gameplay) - 🎯 Mastery of side bets ## Baccarat Achievements ### 🎓 Learning & First Steps Category #### 1. **First Hand** - **ID:** `com.yourdomain.baccarat.first_hand` - **Description:** Play your first hand of Baccarat - **Progress:** Complete on first hand - **Points:** 5 - **Icon:** `play.circle.fill` - **Trigger:** After first `finishRound()` completes #### 2. **Player Believer** - **ID:** `com.yourdomain.baccarat.player_wins_10` - **Description:** Win 10 times betting on Player - **Progress:** Incremental (0-10) - **Points:** 10 - **Icon:** `person.fill` - **Trigger:** When Player bet wins #### 3. **Banker's Trust** - **ID:** `com.yourdomain.baccarat.banker_wins_25` - **Description:** Win 25 times betting on Banker - **Progress:** Incremental (0-25) - **Points:** 15 - **Icon:** `building.columns.fill` - **Trigger:** When Banker bet wins #### 4. **Tie Hunter** - **ID:** `com.yourdomain.baccarat.tie_wins_5` - **Description:** Win 5 times betting on Tie - **Progress:** Incremental (0-5) - **Points:** 15 - **Icon:** "equal.circle.fill" - **Trigger:** When Tie bet wins - **Note:** Higher points due to rarity (14.4% house edge) ### 🎲 Natural & Special Hands Category #### 5. **Natural Talent** - **ID:** `com.yourdomain.baccarat.naturals_10` - **Description:** Get 10 naturals (8 or 9 on initial two cards) - **Progress:** Incremental (0-10) - **Points:** 10 - **Icon:** `star.fill` - **Trigger:** When either Player or Banker gets natural 8 or 9 #### 6. **Natural Legend** - **ID:** `com.yourdomain.baccarat.naturals_50` - **Description:** Get 50 naturals - **Progress:** Incremental (0-50) - **Points:** 25 - **Icon:** `star.circle.fill` - **Trigger:** When either Player or Banker gets natural (extended) #### 7. **Perfect Pair** - **ID:** `com.yourdomain.baccarat.pair_bets_10` - **Description:** Win Player Pair or Banker Pair side bet 10 times - **Progress:** Incremental (0-10) - **Points:** 15 - **Icon:** `suit.heart.fill` - **Trigger:** When either pair bet wins #### 8. **Dragon Master** - **ID:** `com.yourdomain.baccarat.dragon_bonus_10` - **Description:** Win Dragon Bonus side bet 10 times - **Progress:** Incremental (0-10) - **Points:** 15 - **Icon:** `flame.fill` - **Trigger:** When Dragon Bonus bet wins #### 9. **Dragon Legend** - **ID:** `com.yourdomain.baccarat.dragon_bonus_win_by_9` - **Description:** Win Dragon Bonus with a 9-point margin (30:1 payout) - **Progress:** Complete when achieved - **Points:** 25 - **Icon:** `flame.circle.fill` - **Trigger:** When Dragon Bonus pays 30:1 - **Note:** Very rare achievement ### 💪 Persistence & Mastery Category #### 10. **Beginner** - **ID:** `com.yourdomain.baccarat.rounds_50` - **Description:** Play 50 total rounds - **Progress:** Incremental (0-50) - **Points:** 10 - **Icon:** `person.fill` - **Trigger:** After each round completes #### 11. **Enthusiast** - **ID:** `com.yourdomain.baccarat.rounds_250` - **Description:** Play 250 total rounds - **Progress:** Incremental (0-250) - **Points:** 25 - **Icon:** `person.2.fill` - **Trigger:** After each round completes #### 12. **Expert** - **ID:** `com.yourdomain.baccarat.rounds_500` - **Description:** Play 500 total rounds - **Progress:** Incremental (0-500) - **Points:** 50 - **Icon:** `person.3.fill` - **Trigger:** After each round completes #### 13. **Comeback Kid** - **ID:** `com.yourdomain.baccarat.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 ### 📊 Pattern Recognition & Strategy Category #### 14. **Streak Spotter** - **ID:** `com.yourdomain.baccarat.spot_streaks_5` - **Description:** Correctly predict and bet on a streak 5 times (3+ same outcome in a row) - **Progress:** Incremental (0-5) - **Points:** 20 - **Icon:** `chart.line.uptrend.xyaxis` - **Trigger:** When player bets same side 3+ times in a row and all win - **Implementation Note:** Track consecutive wins on same bet type #### 15. **Road Map Reader** - **ID:** `com.yourdomain.baccarat.view_road_map_25` - **Description:** View the road map history 25 times - **Progress:** Incremental (0-25) - **Points:** 10 - **Icon:** `map.fill` - **Trigger:** Track when road map view is expanded/scrolled - **Implementation Note:** Encourages engagement with pattern tracking feature ### 💎 High Stakes Category #### 16. **High Roller** - **ID:** `com.yourdomain.baccarat.bet_50000` - **Description:** Place a single bet of $50,000 or more - **Progress:** Complete when achieved - **Points:** 20 - **Icon:** `dollarsign.circle.fill` - **Trigger:** When any bet equals or exceeds $50,000 - **Implementation Note:** Must be earned through gameplay (requires VIP table limits) #### 17. **Big Win** - **ID:** `com.yourdomain.baccarat.single_win_100000` - **Description:** Win $100,000 or more in a single hand - **Progress:** Complete when achieved - **Points:** 30 - **Icon:** `banknote.fill` - **Trigger:** When net profit from a single round ≥ $100,000 - **Implementation Note:** Possible with Dragon Bonus on large bet ### 🏆 Elite Category #### 18. **Side Bet Specialist** - **ID:** `com.yourdomain.baccarat.side_bets_total_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 (Pairs or Dragon Bonus) #### 19. **James Bond** (Hidden Achievement) - **ID:** `com.yourdomain.baccarat.james_bond` - **Description:** Play 100 consecutive hands betting only on Banker - **Progress:** Incremental (0-100, resets if different bet placed) - **Points:** 25 - **Icon:** `tuxedo.fill` (or `theatermasks.fill`) - **Trigger:** Track consecutive Banker-only bets - **Implementation Note:** Resets to 0 if player bets on Player or Tie - **Fun fact:** James Bond's favorite game and typical bet #### 20. **Table Explorer** (Hidden Achievement) - **ID:** `com.yourdomain.baccarat.all_table_limits` - **Description:** Play at least 10 rounds at each table limit level - **Progress:** Incremental (0-50, 10 per table × 5 tables) - **Points:** 15 - **Icon:** `chart.bar.fill` - **Trigger:** Track rounds played at each table limit (Casual, Low, Medium, High, VIP) ## Implementation Steps ### 1. Define Achievement Enum **File:** `Baccarat/Baccarat/Models/BaccaratAchievement.swift` (new file) ```swift import CasinoKit import GameKit enum BaccaratAchievement: String, AchievementDefinition { case firstHand = "first_hand" case playerWins10 = "player_wins_10" case bankerWins25 = "banker_wins_25" case tieWins5 = "tie_wins_5" case naturals10 = "naturals_10" case naturals50 = "naturals_50" case pairBets10 = "pair_bets_10" case dragonBonus10 = "dragon_bonus_10" case dragonBonusWinBy9 = "dragon_bonus_win_by_9" case rounds50 = "rounds_50" case rounds250 = "rounds_250" case rounds500 = "rounds_500" case comeback = "comeback" case spotStreaks5 = "spot_streaks_5" case viewRoadMap25 = "view_road_map_25" case bet50000 = "bet_50000" case singleWin100000 = "single_win_100000" case sideBetsTotal25 = "side_bets_total_25" case jamesBond = "james_bond" case allTableLimits = "all_table_limits" var identifier: String { "com.yourdomain.baccarat.\(rawValue)" } var title: String { switch self { case .firstHand: return String(localized: "First Hand") case .playerWins10: return String(localized: "Player Believer") case .bankerWins25: return String(localized: "Banker's Trust") case .tieWins5: return String(localized: "Tie Hunter") case .naturals10: return String(localized: "Natural Talent") case .naturals50: return String(localized: "Natural Legend") case .pairBets10: return String(localized: "Perfect Pair") case .dragonBonus10: return String(localized: "Dragon Master") case .dragonBonusWinBy9: return String(localized: "Dragon Legend") case .rounds50: return String(localized: "Beginner") case .rounds250: return String(localized: "Enthusiast") case .rounds500: return String(localized: "Expert") case .comeback: return String(localized: "Comeback Kid") case .spotStreaks5: return String(localized: "Streak Spotter") case .viewRoadMap25: return String(localized: "Road Map Reader") case .bet50000: return String(localized: "High Roller") case .singleWin100000: return String(localized: "Big Win") case .sideBetsTotal25: return String(localized: "Side Bet Specialist") case .jamesBond: return String(localized: "James Bond") case .allTableLimits: return String(localized: "Table Explorer") } } var description: String { // Full descriptions for each achievement } var maxProgress: Int { switch self { case .firstHand, .comeback, .dragonBonusWinBy9, .bet50000, .singleWin100000: return 1 case .tieWins5, .spotStreaks5: return 5 case .playerWins10, .naturals10, .pairBets10, .dragonBonus10: return 10 case .bankerWins25, .sideBetsTotal25, .viewRoadMap25: return 25 case .naturals50, .rounds50, .allTableLimits: return 50 case .jamesBond: return 100 case .rounds250: return 250 case .rounds500: return 500 } } var isIncremental: Bool { switch self { case .firstHand, .comeback, .dragonBonusWinBy9, .bet50000, .singleWin100000: return false default: return true } } var iconName: String { switch self { case .firstHand: return "play.circle.fill" case .playerWins10: return "person.fill" case .bankerWins25: return "building.columns.fill" case .tieWins5: return "equal.circle.fill" case .naturals10: return "star.fill" case .naturals50: return "star.circle.fill" case .pairBets10: return "suit.heart.fill" case .dragonBonus10: return "flame.fill" case .dragonBonusWinBy9: return "flame.circle.fill" case .rounds50: return "person.fill" case .rounds250: return "person.2.fill" case .rounds500: return "person.3.fill" case .comeback: return "arrow.up.right.circle.fill" case .spotStreaks5: return "chart.line.uptrend.xyaxis" case .viewRoadMap25: return "map.fill" case .bet50000: return "dollarsign.circle.fill" case .singleWin100000: return "banknote.fill" case .sideBetsTotal25: return "plus.circle.fill" case .jamesBond: return "theatermasks.fill" case .allTableLimits: return "chart.bar.fill" } } } ``` ### 2. Add Achievement Tracker to GameState **File:** `Baccarat/Baccarat/Engine/GameState.swift` ```swift import CasinoKit @MainActor @Observable class GameState { // ... existing properties ... // NEW: Achievement tracking private(set) var achievementTracker: AchievementTracker // Track session-specific metrics private var sessionLowBalance: Int = 0 private var consecutiveBankerBets = 0 private var consecutiveSameBetType: BetType? = nil private var consecutiveSameBetWins = 0 private var roundsPerTableLimit: [String: Int] = [:] init() { // ... existing init ... self.achievementTracker = AchievementTracker() self.sessionLowBalance = balance } // NEW: Achievement checking methods func checkAchievements(after action: GameAction) { // Called after each game action } 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 `BaccaratEngine.swift` or `GameState.swift`:** ```swift // After round completes func finishRound() { // ... existing logic ... // First hand achievement if totalRoundsPlayed == 1 { achievementTracker.complete(.firstHand) } // Persistence achievements achievementTracker.increment(.rounds50) achievementTracker.increment(.rounds250) achievementTracker.increment(.rounds500) // Track table limits let limitKey = settings.tableLimit.displayName roundsPerTableLimit[limitKey, default: 0] += 1 if roundsPerTableLimit.values.filter({ $0 >= 10 }).count == 5 { achievementTracker.complete(.allTableLimits) } updateSessionTracking() } // When placing bets func placeBet(type: BetType, amount: Int) { // ... existing logic ... // High roller achievement if amount >= 50_000 { achievementTracker.complete(.bet50000) } // James Bond tracking (consecutive Banker bets) if type == .banker { consecutiveBankerBets += 1 if consecutiveBankerBets >= 100 { achievementTracker.complete(.jamesBond) } } else { consecutiveBankerBets = 0 } // Streak tracking if type == consecutiveSameBetType { // Continue tracking } else { consecutiveSameBetType = type consecutiveSameBetWins = 0 } } // After determining winner func evaluateRound() { // ... existing logic ... // Natural achievements if playerHand.isNatural || bankerHand.isNatural { achievementTracker.increment(.naturals10) achievementTracker.increment(.naturals50) } // Check main bet wins if playerBetWon { achievementTracker.increment(.playerWins10) if consecutiveSameBetType == .player { consecutiveSameBetWins += 1 if consecutiveSameBetWins >= 3 { achievementTracker.increment(.spotStreaks5) } } } if bankerBetWon { achievementTracker.increment(.bankerWins25) if consecutiveSameBetType == .banker { consecutiveSameBetWins += 1 if consecutiveSameBetWins >= 3 { achievementTracker.increment(.spotStreaks5) } } } if tieBetWon { achievementTracker.increment(.tieWins5) } // Side bet achievements if playerPairWon || bankerPairWon { achievementTracker.increment(.pairBets10) achievementTracker.increment(.sideBetsTotal25) } if dragonBonusWon { achievementTracker.increment(.dragonBonus10) achievementTracker.increment(.sideBetsTotal25) // Check for 9-point margin win if dragonBonusMargin == 9 { achievementTracker.complete(.dragonBonusWinBy9) } } // Big win achievement let netProfit = calculateNetProfit() if netProfit >= 100_000 { achievementTracker.complete(.singleWin100000) } } // When road map is viewed func trackRoadMapView() { achievementTracker.increment(.viewRoadMap25) } ``` ### 4. Add Road Map View Tracking **File:** `Baccarat/Baccarat/Views/Table/RoadMapView.swift` (or wherever road map is displayed) ```swift .onAppear { state.trackRoadMapView() } ``` ### 5. Add Game Center to Settings **File:** `Baccarat/Baccarat/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() } } } ``` ### 6. Optional: Add Game Center Access Point **File:** `Baccarat/Baccarat/Views/Game/GameTableView.swift` ```swift TopBarView( balance: state.balance, // ... existing parameters ... leadingButtons: [ TopBarButton( icon: "gamecontroller.fill", accessibilityLabel: "Game Center" ) { GameCenterManager.shared.showGameCenterDashboard() } ] ) ``` ### 7. Initialize Game Center on App Launch **File:** `Baccarat/Baccarat/BaccaratApp.swift` ```swift import CasinoKit @main struct BaccaratApp: App { init() { // Authenticate with Game Center silently Task { await GameCenterManager.shared.authenticate() } } // ... rest of app ... } ``` ### 8. Add Localized Strings **File:** `Baccarat/Baccarat/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 Baccarat app 3. Go to Game Center → Achievements 4. Click "+" to add achievement 5. Configure: - **Reference Name:** (internal only) - **Achievement ID:** Must match enum identifier - **Point Value:** As specified above - **Hidden:** Set to "Yes" for James Bond and Table Explorer - **Achievable More Than Once:** No for all - **Localization:** Add EN, ES-MX, FR-CA - **Images:** Upload 512x512 and 1024x1024 versions ## Testing Checklist - [ ] All achievements can be triggered in game - [ ] Incremental achievements show progress - [ ] Hidden achievements don't appear until unlocked - [ ] James Bond achievement resets on non-Banker bet - [ ] Streak tracking works correctly (3+ consecutive wins) - [ ] Road map view tracking increments - [ ] Table limit tracking works across all 5 limits - [ ] Big win achievement triggers at $100k profit - [ ] Dragon Bonus 9-point margin detected correctly - [ ] Comeback achievement tracks session low properly ## Edge Cases to Handle 1. **Player resets game mid-session** - Session achievements (comeback) should reset 2. **Multiple simultaneous bets** - Track all winning bet types for achievements 3. **Tie pushes main bet** - Don't count as "win" for streak tracking 4. **Switching table limits** - Properly track rounds per limit 5. **Offline play** - Queue achievements, submit when online ## Future Enhancements - **Achievement notifications** - Use CasinoKit's AchievementToast - **Progress UI** - Show achievement progress in statistics view - **Pattern hints** - Suggest when player is on a streak (Road Map Reader tie-in) --- ## Summary - ✅ 20 total achievements - ✅ Focus on gameplay understanding, pattern recognition, and milestones - ✅ Two hidden achievements (James Bond, Table Explorer) - ✅ Incremental progress for most achievements - ✅ Unique Baccarat-specific achievements (road maps, Dragon Bonus, streaks) - ✅ Integration with existing GameState and road map system - ✅ 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.*