CasinoGames/Blackjack/GAME_CENTER_PLAN.md

555 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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<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`:**
```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.*