Schafkopf-Server/Sources/App/Model/Tables/WeddingTable.swift

122 lines
4.6 KiB
Swift
Raw Normal View History

2021-12-18 15:08:43 +01:00
import Foundation
final class WeddingTable: AbstractTable<WeddingPlayer> {
var indexOfWeddingOffer: Int
init(table: BiddingTable, offerer: BiddingPlayer) {
let players = table.players.map { WeddingPlayer(player: $0, offersWedding: $0 == offerer) }
indexOfWeddingOffer = table.players.index(of: offerer)
super.init(table: table, players: players)
}
var hasRemainingActors: Bool {
players.contains { $0.requiresAction }
}
var requiresCardSelection: Bool {
players.contains { $0.selectsGame }
}
override var playedGame: GameType? {
.hochzeit
}
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 wedding table \(self.name)")
return (.tableStateInvalid, nil)
}
guard player.canPerform(action) else {
return (.tableStateInvalid, nil)
}
switch action {
case .acceptWedding:
return performWeddingAccept(forPlayer: player)
case .withdrawFromAuction:
return performWithdrawl(forPlayer: player)
case .increaseOrMatchGame:
fatalError()
default:
return (.tableStateInvalid, nil)
}
}
private func performWeddingAccept(forPlayer player: WeddingPlayer) -> (result: PlayerActionResult, table: ManageableTable?) {
guard player.requiresAction else {
return (.tableStateInvalid, nil)
}
player.state = .wouldAcceptWedding
guard !hasRemainingActors else {
return (.success, nil)
}
// Nobody wants to play a higher game, so let the first player accept the wedding
players.first { $0.wouldAcceptWedding }!.selectsGame = true
return (.success, nil)
}
private func performWithdrawl(forPlayer player: WeddingPlayer) -> (result: PlayerActionResult, table: ManageableTable?) {
guard player.requiresAction else {
return (.tableStateInvalid, nil)
}
player.state = .withdrawnFromAuction
guard !hasRemainingActors else {
return (.success, nil)
}
// Nobody wants to play a higher game, so let the first player accept the wedding
guard let player = players.first(where: { $0.wouldAcceptWedding }) else {
// Nobody wants to accept the wedding or play something higher, so abort the game
let table = WaitingTable(oldTableAdvancedByOne: self)
return (.success, table)
}
player.selectsGame = true
return (.success, nil)
}
private func performOutbid(forPlayer player: WeddingPlayer) -> (result: PlayerActionResult, table: ManageableTable?) {
guard player.requiresAction else {
return (.tableStateInvalid, nil)
}
let table = BiddingTable(wedding: self, outbidBy: player)
return (.success, table)
}
override func playerData(at index: Int) -> (actions: [PlayerAction], games: [GameConvertible], cards: [PlayableCard], selectsGame: Bool) {
guard requiresCardSelection else {
return super.playerData(at: index)
}
let player = players[index]
guard player.selectsGame else {
return super.playerData(at: index)
}
return (actions: player.actions, games: [], cards: player.exchangeableCards, selectsGame: false)
}
override func play(card: Card, player name: PlayerName) -> (result: PlayerActionResult, table: ManageableTable?) {
guard requiresCardSelection else {
print("Wedding is not in stage where card should be selected")
return (.tableStateInvalid, nil)
}
guard let player = players.player(named: name) else {
print("Player \(name) unexpectedly missing from wedding table \(self.name)")
return (.tableStateInvalid, nil)
}
guard player.selectsGame else {
print("Player \(name) is not the one selecting a wedding card")
return (.tableStateInvalid, nil)
}
guard player.canExchange(card: card) else {
print("Invalid card \(card) to exchange in wedding")
return (.tableStateInvalid, nil)
}
let offerer = players[indexOfWeddingOffer]
let trumpCard = offerer.replaceWeddingCard(with: card)
player.replace(card, with: trumpCard)
let table = PlayingTable(wedding: self, offeredBy: offerer, acceptedBy: player)
return (.success, table)
}
}