Complete native rewrite of the web-based SoliCards game as a SwiftUI multiplatform app targeting iOS 17+, iPadOS 17+, and macOS 14+. Three solitaire variants (Klondike, Spider, FreeCell) with full game rules, drag & drop, smart zoom layout, 6 themes, 4 difficulty levels, SwiftData persistence, VoiceOver accessibility, and 57 unit tests. Key features: - MVVM + Protocol-Oriented Strategy architecture - DragGesture with coordinate-space hit-testing (long press + drag) - Smart zoom: cards auto-size to fit screen based on deepest column - Landscape: 30% bigger cards with scrollable overflow (iOS) - macOS: 120pt card cap, 92% height buffer for window resizing - Auto-save, game resume, statistics tracking via SwiftData - Privacy manifest, app icon, String Catalog, zero dependencies Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
39 lines
1.5 KiB
Swift
39 lines
1.5 KiB
Swift
import Foundation
|
|
|
|
enum AutoCompleter {
|
|
/// Finds the next card that can be auto-moved to a foundation.
|
|
/// Returns the source location and foundation index, or nil if no move is available.
|
|
static func findNextAutoMove(state: GameSnapshot, rules: GameRules) -> (from: CardLocation, to: CardLocation)? {
|
|
// Check waste pile
|
|
if let topWaste = state.waste.last {
|
|
for (i, foundation) in state.foundations.enumerated() {
|
|
if MoveValidator.canPlaceOnFoundation(topWaste, topCard: foundation.last) {
|
|
return (.waste, .foundation(i))
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check free cells
|
|
for (cellIndex, cell) in state.freeCells.enumerated() {
|
|
guard let card = cell else { continue }
|
|
for (i, foundation) in state.foundations.enumerated() {
|
|
if MoveValidator.canPlaceOnFoundation(card, topCard: foundation.last) {
|
|
return (.freeCell(cellIndex), .foundation(i))
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check tableau tops
|
|
for (tabIndex, tableau) in state.tableaus.enumerated() {
|
|
guard let topCard = tableau.last, topCard.isFaceUp else { continue }
|
|
for (i, foundation) in state.foundations.enumerated() {
|
|
if MoveValidator.canPlaceOnFoundation(topCard, topCard: foundation.last) {
|
|
return (.tableau(tabIndex), .foundation(i))
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
}
|