import Foundation final class DealingTable: AbstractTable { init(table: WaitingTable) { let cards = Dealer.dealFirstCards() let players = table.players.map(DealingPlayer.init) for (index, player) in players.enumerated() { player.cards = cards[index] } super.init(table: table, players: players) } /// All players either doubled or didn't double var allPlayersActed: Bool { !players.contains { !$0.didDecide } } /// At least one player placed a bid var hasDouble: Bool { players.contains { $0.didDouble } } override func perform(action: PlayerAction, forPlayer name: PlayerName) -> (result: PlayerActionResult, table: ManageableTable?) { guard let player = players.player(named: name) else { print("Player \(name) unexpectedly missing from dealing table \(self.name)") return (.tableStateInvalid, nil) } guard player.canPerform(action) else { return (.tableStateInvalid, nil) } switch action { case .initialDoubleCost: return perform(double: true, forPlayer: player) case .noDoubleCost: return perform(double: false, forPlayer: player) default: return (.tableStateInvalid, nil) } } private func perform(double: Bool, forPlayer player: DealingPlayer) -> (result: PlayerActionResult, table: ManageableTable?) { guard !player.didDecide else { return (.tableStateInvalid, nil) } player.didDouble = double player.didDecide = true guard allPlayersActed else { return (.success, nil) } guard hasDouble else { // Revert to a waiting table and switch to the next player let table = WaitingTable(oldTableAdvancedByOne: self) return (.success, table) } // Automatically adds remaining cards to the players let table = BiddingTable(table: self) return (.success, table) } override func cards(forPlayerAt index: Int) -> [PlayableCard] { players[index].cards.unplayable } }