17 KiB
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
GameStatewhen 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.showCountis 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:
- Log into App Store Connect
- Select Blackjack app
- Go to Game Center → Achievements
- Click "+" to add achievement
- 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
- Player resets game mid-session - Session achievements (comeback) should reset
- Player changes rule variations - Track separately for "Rule Breaker"
- Player disables hints - Strategy achievements still trackable via engine logic
- Offline play - Queue achievements, submit when online
- 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.