Refactor table + player data, add state
This commit is contained in:
parent
49787db1aa
commit
3a95e1c990
@ -280,7 +280,7 @@ function setInfoForPlayer(player, position, game) {
|
|||||||
state.push(double)
|
state.push(double)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game != null) {
|
if (game != null && player.hasOwnProperty("points")) {
|
||||||
state.push(player.points.toString() + " Punkte")
|
state.push(player.points.toString() + " Punkte")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,33 +6,28 @@ struct PlayerInfo: Codable, Equatable {
|
|||||||
let name: PlayerName
|
let name: PlayerName
|
||||||
|
|
||||||
/// Indicates that the player is active, i.e. a session is established
|
/// Indicates that the player is active, i.e. a session is established
|
||||||
let isConnected: Bool
|
var isConnected = false
|
||||||
|
|
||||||
/// The player is the next one to perform an action
|
/// The player is the next one to perform an action
|
||||||
let isNextActor: Bool
|
var isNextActor = false
|
||||||
|
|
||||||
/// The card which the player added to the current trick
|
/// The card which the player added to the current trick
|
||||||
let playedCard: CardId?
|
var playedCard: CardId? = nil
|
||||||
|
|
||||||
/// The height of the player card on the table stack
|
/// The height of the player card on the table stack
|
||||||
let positionInTrick: Int
|
var positionInTrick = 0
|
||||||
|
|
||||||
/// The number of times the player doubled the game cost (initial double and raises)
|
/// The number of times the player doubled the game cost (initial double and raises)
|
||||||
let numberOfDoubles: Int
|
var numberOfDoubles = 0
|
||||||
|
|
||||||
let leadsGame: Bool
|
var leadsGame = false
|
||||||
|
|
||||||
let points: Int?
|
var points: Int? = nil
|
||||||
|
|
||||||
init(player: Player, position: Int) {
|
var state: [PlayerStateId] = []
|
||||||
self.name = player.name
|
|
||||||
self.isConnected = player.isConnected
|
init(name: PlayerName) {
|
||||||
self.isNextActor = player.isNextActor
|
self.name = name
|
||||||
self.positionInTrick = position
|
|
||||||
self.playedCard = player.playedCard?.id
|
|
||||||
self.numberOfDoubles = player.numberOfDoubles
|
|
||||||
self.leadsGame = player.leadsGame
|
|
||||||
self.points = player.points
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the property names into shorter strings for JSON encoding
|
/// Convert the property names into shorter strings for JSON encoding
|
||||||
|
@ -6,39 +6,29 @@ struct TableInfo: Codable {
|
|||||||
|
|
||||||
let name: String
|
let name: String
|
||||||
|
|
||||||
let player: PlayerInfo
|
var player: PlayerInfo = .init(name: "")
|
||||||
|
|
||||||
let playerLeft: PlayerInfo?
|
var playerLeft: PlayerInfo? = nil
|
||||||
|
|
||||||
let playerAcross: PlayerInfo?
|
var playerAcross: PlayerInfo? = nil
|
||||||
|
|
||||||
let playerRight: PlayerInfo?
|
var playerRight: PlayerInfo? = nil
|
||||||
|
|
||||||
let playableGames: [GameId]
|
var playableGames: [GameId] = []
|
||||||
|
|
||||||
/// The cards in the hand of the player
|
/// The cards in the hand of the player
|
||||||
let cards: [CardInfo]
|
var cards: [CardInfo] = []
|
||||||
|
|
||||||
/// The action the player can perform
|
/// The action the player can perform
|
||||||
let actions: [ActionId]
|
var actions: [ActionId] = []
|
||||||
|
|
||||||
let playerSelectsGame: Bool
|
var playerSelectsGame = false
|
||||||
|
|
||||||
let game: GameId?
|
var game: GameId? = nil
|
||||||
|
|
||||||
init<T>(table: AbstractTable<T>, index: Int) {
|
init(id: TableId, name: TableName) {
|
||||||
self.id = table.id
|
self.id = id
|
||||||
self.name = table.name
|
self.name = name
|
||||||
self.player = table.playerInfo(forIndex: index)!
|
|
||||||
self.playerLeft = table.playerInfo(forIndex: (index + 1) % 4)
|
|
||||||
self.playerAcross = table.playerInfo(forIndex: (index + 2) % 4)
|
|
||||||
self.playerRight = table.playerInfo(forIndex: (index + 3) % 4)
|
|
||||||
let data = table.playerData(at: index)
|
|
||||||
self.playableGames = data.games.map { $0.id }
|
|
||||||
self.actions = data.actions.map { $0.id }
|
|
||||||
self.cards = data.cards.map { $0.cardInfo }
|
|
||||||
self.playerSelectsGame = data.selectsGame
|
|
||||||
self.game = table.playedGame?.id
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
typealias PlayerStateId = String
|
||||||
|
|
||||||
enum PlayerState: String {
|
enum PlayerState: String {
|
||||||
|
|
||||||
case canDouble
|
case canDouble = "canDouble"
|
||||||
case didDouble
|
case didDouble = "doubled"
|
||||||
|
|
||||||
case isDisconnected
|
case isDisconnected = "offline"
|
||||||
|
|
||||||
case mustBid
|
case mustBid = "bidder"
|
||||||
case didFold
|
case didFold = "fold"
|
||||||
case didBid
|
case didBid = "bid"
|
||||||
case mustPlaceBid
|
|
||||||
|
|
||||||
case isGameSelector
|
case isGameSelector = "selects"
|
||||||
case isWeddingOfferer
|
case isWeddingOfferer = "wedding"
|
||||||
case isCalled
|
case isCalled = "called"
|
||||||
|
|
||||||
case didRaise
|
case didRaise = "raised"
|
||||||
|
case leadsGame = "leads"
|
||||||
|
|
||||||
case isWinner
|
case isWinner = "winner"
|
||||||
case isLooser
|
case isLooser = "looser"
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import WebSocketKit
|
import WebSocketKit
|
||||||
|
|
||||||
final class BiddingPlayer: Player {
|
final class BiddingPlayer: CardHoldingPlayer {
|
||||||
|
|
||||||
var isStillBidding = true
|
var isStillBidding = true
|
||||||
|
|
||||||
var isAllowedToOfferWedding: Bool
|
var isAllowedToOfferWedding: Bool
|
||||||
|
|
||||||
var selectsGame = false
|
|
||||||
|
|
||||||
init(player: DealingPlayer) {
|
init(player: DealingPlayer) {
|
||||||
isAllowedToOfferWedding = true
|
isAllowedToOfferWedding = true
|
||||||
super.init(player: player)
|
super.init(player: player)
|
||||||
@ -47,9 +45,18 @@ final class BiddingPlayer: Player {
|
|||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
override var points: Int? {
|
private var biddingState: [PlayerState] {
|
||||||
get { nil }
|
isStillBidding ? [] : [.didFold]
|
||||||
set { }
|
}
|
||||||
|
|
||||||
|
override var states: [PlayerState] {
|
||||||
|
var states = super.states
|
||||||
|
if !isStillBidding {
|
||||||
|
states.append(.didFold)
|
||||||
|
} else if isNextActor {
|
||||||
|
states.append(.mustBid)
|
||||||
|
}
|
||||||
|
return states
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
40
Sources/App/Model/Players/CardHoldingPlayer.swift
Normal file
40
Sources/App/Model/Players/CardHoldingPlayer.swift
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
class CardHoldingPlayer: Player {
|
||||||
|
|
||||||
|
var didDouble: Bool
|
||||||
|
|
||||||
|
var cards: [Card]
|
||||||
|
|
||||||
|
var selectsGame = false
|
||||||
|
|
||||||
|
override init(player: Player) {
|
||||||
|
self.cards = []
|
||||||
|
self.didDouble = false
|
||||||
|
super.init(player: player)
|
||||||
|
}
|
||||||
|
|
||||||
|
init(player: CardHoldingPlayer) {
|
||||||
|
self.cards = player.cards
|
||||||
|
self.didDouble = player.didDouble
|
||||||
|
self.selectsGame = player.selectsGame
|
||||||
|
super.init(player: player)
|
||||||
|
}
|
||||||
|
|
||||||
|
override var states: [PlayerState] {
|
||||||
|
var states = super.states
|
||||||
|
if didDouble {
|
||||||
|
states.append(.didDouble)
|
||||||
|
}
|
||||||
|
if selectsGame {
|
||||||
|
states.append(.isGameSelector)
|
||||||
|
}
|
||||||
|
return states
|
||||||
|
}
|
||||||
|
|
||||||
|
override var info: PlayerInfo {
|
||||||
|
var info = super.info
|
||||||
|
info.numberOfDoubles = didDouble ? 1 : 0
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
}
|
@ -1,35 +1,28 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import WebSocketKit
|
import WebSocketKit
|
||||||
|
|
||||||
final class DealingPlayer: Player {
|
final class DealingPlayer: CardHoldingPlayer {
|
||||||
|
|
||||||
var didDouble: Bool? = nil
|
var didDecide = false
|
||||||
|
|
||||||
override var isNextActor: Bool {
|
|
||||||
get { didDouble == nil }
|
|
||||||
set { }
|
|
||||||
}
|
|
||||||
|
|
||||||
override var actions: [PlayerAction] {
|
override var actions: [PlayerAction] {
|
||||||
didDouble == nil ? [.initialDoubleCost, .noDoubleCost] : []
|
didDecide ? [] : [.initialDoubleCost, .noDoubleCost]
|
||||||
}
|
}
|
||||||
|
|
||||||
init(player: WaitingPlayer) {
|
init(player: WaitingPlayer) {
|
||||||
super.init(player: player)
|
super.init(player: player)
|
||||||
}
|
}
|
||||||
|
|
||||||
override var numberOfDoubles: Int {
|
override var states: [PlayerState] {
|
||||||
get { didDouble == true ? 1 : 0 }
|
var states = super.states
|
||||||
set { }
|
if !didDecide {
|
||||||
|
states.append(.canDouble)
|
||||||
|
}
|
||||||
|
return states
|
||||||
}
|
}
|
||||||
|
|
||||||
override var leadsGame: Bool {
|
override var isNextActor: Bool {
|
||||||
get { false }
|
get { !didDecide }
|
||||||
set { }
|
|
||||||
}
|
|
||||||
|
|
||||||
override var points: Int? {
|
|
||||||
get { nil }
|
|
||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,20 +2,32 @@ import Foundation
|
|||||||
|
|
||||||
final class FinishedPlayer: Player {
|
final class FinishedPlayer: Player {
|
||||||
|
|
||||||
let tricks: [Trick]
|
let points: Int
|
||||||
|
|
||||||
|
let leadsGame: Bool
|
||||||
|
|
||||||
|
let playedCard: Card
|
||||||
|
|
||||||
init(player: PlayingPlayer) {
|
init(player: PlayingPlayer) {
|
||||||
self.tricks = player.wonTricks
|
self.points = player.wonTricks.map { $0.points }.reduce(0, +)
|
||||||
|
self.leadsGame = player.leadsGame
|
||||||
|
self.playedCard = player.playedCard!
|
||||||
super.init(player: player)
|
super.init(player: player)
|
||||||
}
|
}
|
||||||
|
|
||||||
override var points: Int? {
|
|
||||||
get { tricks.map { $0.points }.reduce(0, +) }
|
|
||||||
set { }
|
|
||||||
}
|
|
||||||
|
|
||||||
override var actions: [PlayerAction] {
|
override var actions: [PlayerAction] {
|
||||||
[.deal]
|
[.deal]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var states: [PlayerState] {
|
||||||
|
super.states + [] // TODO: Finish
|
||||||
|
}
|
||||||
|
|
||||||
|
override var info: PlayerInfo {
|
||||||
|
var result = super.info
|
||||||
|
result.points = points
|
||||||
|
result.playedCard = playedCard.id
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,44 +7,35 @@ class Player {
|
|||||||
|
|
||||||
var socket: WebSocket?
|
var socket: WebSocket?
|
||||||
|
|
||||||
var playedCard: Card?
|
|
||||||
|
|
||||||
var isNextActor: Bool
|
var isNextActor: Bool
|
||||||
|
|
||||||
var cards: [Card]
|
|
||||||
|
|
||||||
var numberOfDoubles: Int
|
|
||||||
|
|
||||||
var leadsGame: Bool
|
|
||||||
|
|
||||||
var points: Int?
|
|
||||||
|
|
||||||
init(name: PlayerName, socket: WebSocket? = nil) {
|
init(name: PlayerName, socket: WebSocket? = nil) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.socket = socket
|
self.socket = socket
|
||||||
self.cards = []
|
|
||||||
self.isNextActor = false
|
self.isNextActor = false
|
||||||
self.playedCard = nil
|
|
||||||
self.numberOfDoubles = 0
|
|
||||||
self.leadsGame = false
|
|
||||||
self.points = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init(player: Player) {
|
init(player: Player) {
|
||||||
self.name = player.name
|
self.name = player.name
|
||||||
self.socket = player.socket
|
self.socket = player.socket
|
||||||
self.cards = player.cards
|
|
||||||
self.isNextActor = false
|
self.isNextActor = false
|
||||||
self.playedCard = player.playedCard
|
|
||||||
self.numberOfDoubles = player.numberOfDoubles
|
|
||||||
self.leadsGame = player.leadsGame
|
|
||||||
self.points = player.points
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var actions: [PlayerAction] {
|
var actions: [PlayerAction] {
|
||||||
[]
|
[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var states: [PlayerState] {
|
||||||
|
isConnected ? [] : [.isDisconnected]
|
||||||
|
}
|
||||||
|
|
||||||
|
var info: PlayerInfo {
|
||||||
|
var result = PlayerInfo(name: name)
|
||||||
|
result.isConnected = isConnected
|
||||||
|
result.isNextActor = isNextActor
|
||||||
|
result.state = states.map { $0.rawValue }
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Player: Equatable {
|
extension Player: Equatable {
|
||||||
|
@ -7,18 +7,26 @@ import WebSocketKit
|
|||||||
*/
|
*/
|
||||||
private let numberOfCardsToProtectAce = 4
|
private let numberOfCardsToProtectAce = 4
|
||||||
|
|
||||||
final class PlayingPlayer: Player {
|
final class PlayingPlayer: CardHoldingPlayer {
|
||||||
|
|
||||||
var canStillRaise = true
|
var canStillRaise = true
|
||||||
|
|
||||||
var isCalledWithAce: Card?
|
var isCalledWithAce: Card?
|
||||||
|
|
||||||
|
var didPlayCalledAce = false
|
||||||
|
|
||||||
|
var playedCard: Card?
|
||||||
|
|
||||||
|
var leadsGame: Bool
|
||||||
|
|
||||||
|
var numberOfDoubles = 0
|
||||||
|
|
||||||
/// All tricks won by the player in this game
|
/// All tricks won by the player in this game
|
||||||
var wonTricks: [Trick] = []
|
var wonTricks: [Trick] = []
|
||||||
|
|
||||||
init(player: Player, leads: Bool, calledAce ace: Card?) {
|
init(player: CardHoldingPlayer, leads: Bool, calledAce ace: Card?) {
|
||||||
super.init(player: player)
|
|
||||||
leadsGame = leads
|
leadsGame = leads
|
||||||
|
super.init(player: player)
|
||||||
if let ace = ace, cards.contains(ace) {
|
if let ace = ace, cards.contains(ace) {
|
||||||
isCalledWithAce = ace
|
isCalledWithAce = ace
|
||||||
} else {
|
} else {
|
||||||
@ -26,8 +34,19 @@ final class PlayingPlayer: Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var isUnknownCallee: Bool {
|
||||||
|
isCalledWithAce != nil && !didPlayCalledAce
|
||||||
|
}
|
||||||
|
|
||||||
override var actions: [PlayerAction] {
|
override var actions: [PlayerAction] {
|
||||||
guard canStillRaise, leadsGame == (isCalledWithAce != nil) else {
|
guard canStillRaise else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
if isUnknownCallee && leadsGame {
|
||||||
|
// Player belongs to caller, but other side has raised
|
||||||
|
return [.doubleDuringGame]
|
||||||
|
}
|
||||||
|
guard !leadsGame else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return [.doubleDuringGame]
|
return [.doubleDuringGame]
|
||||||
@ -38,7 +57,7 @@ final class PlayingPlayer: Player {
|
|||||||
cards = cards.filter { $0 != card }
|
cards = cards.filter { $0 != card }
|
||||||
if card == isCalledWithAce {
|
if card == isCalledWithAce {
|
||||||
leadsGame.toggle()
|
leadsGame.toggle()
|
||||||
isCalledWithAce = nil
|
didPlayCalledAce = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,4 +155,24 @@ final class PlayingPlayer: Player {
|
|||||||
var currentPoints: Int {
|
var currentPoints: Int {
|
||||||
wonTricks.map { $0.points }.reduce(0, +)
|
wonTricks.map { $0.points }.reduce(0, +)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var states: [PlayerState] {
|
||||||
|
var states = super.states
|
||||||
|
if didPlayCalledAce {
|
||||||
|
states.append(.isCalled)
|
||||||
|
}
|
||||||
|
if leadsGame {
|
||||||
|
states.append(.leadsGame)
|
||||||
|
}
|
||||||
|
if numberOfDoubles > 0 {
|
||||||
|
states.append(.didRaise)
|
||||||
|
}
|
||||||
|
return states
|
||||||
|
}
|
||||||
|
|
||||||
|
override var info: PlayerInfo {
|
||||||
|
var info = super.info
|
||||||
|
info.playedCard = playedCard?.id
|
||||||
|
return info
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,15 +8,4 @@ final class WaitingPlayer: Player {
|
|||||||
override var actions: [PlayerAction] {
|
override var actions: [PlayerAction] {
|
||||||
canStartGame ? [.deal] : []
|
canStartGame ? [.deal] : []
|
||||||
}
|
}
|
||||||
|
|
||||||
override var leadsGame: Bool {
|
|
||||||
get { false }
|
|
||||||
set { }
|
|
||||||
}
|
|
||||||
|
|
||||||
override var points: Int? {
|
|
||||||
get { nil }
|
|
||||||
set { }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class WeddingPlayer: Player {
|
final class WeddingPlayer: CardHoldingPlayer {
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
case requiresAction
|
case requiresAction
|
||||||
@ -16,7 +16,7 @@ final class WeddingPlayer: Player {
|
|||||||
state == .requiresAction
|
state == .requiresAction
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectsGame: Bool {
|
override var selectsGame: Bool {
|
||||||
get {
|
get {
|
||||||
state == .selectsGame
|
state == .selectsGame
|
||||||
}
|
}
|
||||||
@ -38,6 +38,14 @@ final class WeddingPlayer: Player {
|
|||||||
super.init(player: player)
|
super.init(player: player)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var states: [PlayerState] {
|
||||||
|
var states = super.states
|
||||||
|
if offersWedding {
|
||||||
|
states.append(.isWeddingOfferer)
|
||||||
|
}
|
||||||
|
return states
|
||||||
|
}
|
||||||
|
|
||||||
override var actions: [PlayerAction] {
|
override var actions: [PlayerAction] {
|
||||||
guard state == .requiresAction else {
|
guard state == .requiresAction else {
|
||||||
return []
|
return []
|
||||||
@ -57,16 +65,6 @@ final class WeddingPlayer: Player {
|
|||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
override var points: Int? {
|
|
||||||
get { nil }
|
|
||||||
set { }
|
|
||||||
}
|
|
||||||
|
|
||||||
override var leadsGame: Bool {
|
|
||||||
get { offersWedding || selectsGame }
|
|
||||||
set { }
|
|
||||||
}
|
|
||||||
|
|
||||||
func canExchange(card: Card) -> Bool {
|
func canExchange(card: Card) -> Bool {
|
||||||
cards.filter { !$0.isTrump(in: .hochzeit) }.contains(card)
|
cards.filter { !$0.isTrump(in: .hochzeit) }.contains(card)
|
||||||
}
|
}
|
||||||
@ -86,4 +84,10 @@ final class WeddingPlayer: Player {
|
|||||||
func replace(_ card: Card, with trumpCard: Card) {
|
func replace(_ card: Card, with trumpCard: Card) {
|
||||||
cards = (cards.filter { $0 != card } + [trumpCard]).sortedCards(forGame: .hochzeit)
|
cards = (cards.filter { $0 != card } + [trumpCard]).sortedCards(forGame: .hochzeit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var info: PlayerInfo {
|
||||||
|
var info = super.info
|
||||||
|
info.leadsGame = offersWedding || selectsGame
|
||||||
|
return info
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,15 +45,36 @@ class AbstractTable<TablePlayer> where TablePlayer: Player {
|
|||||||
(.tableStateInvalid, nil)
|
(.tableStateInvalid, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func playerData(at index: Int) -> (actions: [PlayerAction], games: [GameConvertible], cards: [PlayableCard], selectsGame: Bool) {
|
|
||||||
let player = players[index]
|
|
||||||
return (actions: player.actions, games: [], cards: player.cards.unplayable, selectsGame: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cardStackPosition(ofPlayerAt index: Int) -> Int {
|
func cardStackPosition(ofPlayerAt index: Int) -> Int {
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cards(forPlayerAt index: Int) -> [PlayableCard] {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
func games(forPlayerAt index: Int) -> [GameConvertible] {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
func gameIsSelected(byPlayerAt index: Int) -> Bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableInfo(forPlayerAt index: Int) -> TableInfo {
|
||||||
|
var info = TableInfo(id: id, name: name)
|
||||||
|
info.player = playerInfo(forIndex: index)!
|
||||||
|
info.playerLeft = playerInfo(forIndex: (index + 1) % 4)
|
||||||
|
info.playerAcross = playerInfo(forIndex: (index + 2) % 4)
|
||||||
|
info.playerRight = playerInfo(forIndex: (index + 3) % 4)
|
||||||
|
info.playableGames = games(forPlayerAt: index).map { $0.id }
|
||||||
|
info.actions = players[index].actions.map { $0.id }
|
||||||
|
info.cards = cards(forPlayerAt: index).map { $0.cardInfo }
|
||||||
|
info.playerSelectsGame = gameIsSelected(byPlayerAt: index)
|
||||||
|
info.game = playedGame?.id
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AbstractTable: ManageableTable {
|
extension AbstractTable: ManageableTable {
|
||||||
@ -111,7 +132,9 @@ extension AbstractTable: ManageableTable {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
let height = cardStackPosition(ofPlayerAt: index)
|
let height = cardStackPosition(ofPlayerAt: index)
|
||||||
return PlayerInfo(player: player, position: height)
|
var info = player.info
|
||||||
|
info.positionInTrick = height
|
||||||
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableInfo(forPlayer player: PlayerName) -> TableInfo {
|
func tableInfo(forPlayer player: PlayerName) -> TableInfo {
|
||||||
@ -119,9 +142,5 @@ extension AbstractTable: ManageableTable {
|
|||||||
return tableInfo(forPlayerAt: index)
|
return tableInfo(forPlayerAt: index)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableInfo(forPlayerAt index: Int) -> TableInfo {
|
|
||||||
.init(table: self, index: index)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,18 +164,22 @@ final class BiddingTable: AbstractTable<BiddingPlayer> {
|
|||||||
return (.success, nil)
|
return (.success, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func playerData(at index: Int) -> (actions: [PlayerAction], games: [GameConvertible], cards: [PlayableCard], selectsGame: Bool) {
|
override func cards(forPlayerAt index: Int) -> [PlayableCard] {
|
||||||
let player = players[index]
|
players[index].cards.unplayable
|
||||||
|
|
||||||
let games: [GameConvertible]
|
|
||||||
if isWaitingForGameSelection {
|
|
||||||
games = gameToOutbid.availableGames.filter(player.canPlay)
|
|
||||||
} else if index <= indexOfHighestBidder {
|
|
||||||
games = gameToOutbid.availableClasses
|
|
||||||
} else {
|
|
||||||
games = gameToOutbid.classesWhenOutbidding
|
|
||||||
}
|
|
||||||
return (player.actions, games, player.cards.unplayable, selectsGame: player.selectsGame)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func games(forPlayerAt index: Int) -> [GameConvertible] {
|
||||||
|
if isWaitingForGameSelection {
|
||||||
|
let player = players[index]
|
||||||
|
return gameToOutbid.availableGames.filter(player.canPlay)
|
||||||
|
}
|
||||||
|
if index <= indexOfHighestBidder {
|
||||||
|
return gameToOutbid.availableClasses
|
||||||
|
}
|
||||||
|
return gameToOutbid.classesWhenOutbidding
|
||||||
|
}
|
||||||
|
|
||||||
|
override func gameIsSelected(byPlayerAt index: Int) -> Bool {
|
||||||
|
players[index].selectsGame
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,17 @@ final class DealingTable: AbstractTable<DealingPlayer> {
|
|||||||
|
|
||||||
init(table: WaitingTable) {
|
init(table: WaitingTable) {
|
||||||
let cards = Dealer.dealFirstCards()
|
let cards = Dealer.dealFirstCards()
|
||||||
for (index, player) in table.players.enumerated() {
|
let players = table.players.map(DealingPlayer.init)
|
||||||
|
for (index, player) in players.enumerated() {
|
||||||
player.cards = cards[index]
|
player.cards = cards[index]
|
||||||
}
|
}
|
||||||
let players = table.players.map(DealingPlayer.init)
|
|
||||||
super.init(table: table, players: players)
|
super.init(table: table, players: players)
|
||||||
|
print("\(self.players[0].cards.count) cards")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All players either doubled or didn't double
|
/// All players either doubled or didn't double
|
||||||
var allPlayersActed: Bool {
|
var allPlayersActed: Bool {
|
||||||
!players.contains { $0.didDouble == nil }
|
!players.contains { !$0.didDecide }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// At least one player placed a bid
|
/// At least one player placed a bid
|
||||||
@ -41,7 +42,7 @@ final class DealingTable: AbstractTable<DealingPlayer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func perform(double: Bool, forPlayer player: DealingPlayer) -> (result: PlayerActionResult, table: ManageableTable?) {
|
private func perform(double: Bool, forPlayer player: DealingPlayer) -> (result: PlayerActionResult, table: ManageableTable?) {
|
||||||
guard player.didDouble == nil else {
|
guard !player.didDecide else {
|
||||||
return (.tableStateInvalid, nil)
|
return (.tableStateInvalid, nil)
|
||||||
}
|
}
|
||||||
player.didDouble = double
|
player.didDouble = double
|
||||||
@ -58,4 +59,7 @@ final class DealingTable: AbstractTable<DealingPlayer> {
|
|||||||
return (.success, table)
|
return (.success, table)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func cards(forPlayerAt index: Int) -> [PlayableCard] {
|
||||||
|
players[index].cards.unplayable
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,12 +47,16 @@ final class FinishedTable: AbstractTable<FinishedPlayer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(table: PlayingTable) {
|
init(table: PlayingTable) {
|
||||||
|
|
||||||
let players = table.players.map(FinishedPlayer.init)
|
let players = table.players.map(FinishedPlayer.init)
|
||||||
self.game = table.game
|
self.game = table.game
|
||||||
leadingPoints = players
|
leadingPoints = players
|
||||||
.filter { $0.leadsGame }
|
.filter { $0.leadsGame }
|
||||||
.map { $0.points! }
|
.map { $0.points }
|
||||||
.reduce(0, +)
|
.reduce(0, +)
|
||||||
|
// TODO: Set isNextActor for winners
|
||||||
|
// TODO: Check for bettel
|
||||||
|
// TODO: Set schneider, schwarz, cost
|
||||||
super.init(table: table, players: players)
|
super.init(table: table, players: players)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,10 +108,8 @@ final class PlayingTable: AbstractTable<PlayingPlayer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func playerData(at index: Int) -> (actions: [PlayerAction], games: [GameConvertible], cards: [PlayableCard], selectsGame: Bool) {
|
override func cards(forPlayerAt index: Int) -> [PlayableCard] {
|
||||||
let player = players[index]
|
players[index].playableCards(for: nextTrick, in: game)
|
||||||
let cards = player.playableCards(for: nextTrick, in: game)
|
|
||||||
return (actions: player.actions, games: [], cards: cards, selectsGame: false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func didFinish(trick: Trick, in game: GameType) -> (result: PlayerActionResult, table: ManageableTable?) {
|
private func didFinish(trick: Trick, in game: GameType) -> (result: PlayerActionResult, table: ManageableTable?) {
|
||||||
|
@ -82,15 +82,16 @@ final class WeddingTable: AbstractTable<WeddingPlayer> {
|
|||||||
return (.success, table)
|
return (.success, table)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func playerData(at index: Int) -> (actions: [PlayerAction], games: [GameConvertible], cards: [PlayableCard], selectsGame: Bool) {
|
override func cards(forPlayerAt index: Int) -> [PlayableCard] {
|
||||||
guard requiresCardSelection else {
|
|
||||||
return super.playerData(at: index)
|
|
||||||
}
|
|
||||||
let player = players[index]
|
let player = players[index]
|
||||||
guard player.selectsGame else {
|
guard requiresCardSelection, player.selectsGame else {
|
||||||
return super.playerData(at: index)
|
return player.cards.unplayable
|
||||||
}
|
}
|
||||||
return (actions: player.actions, games: [], cards: player.exchangeableCards, selectsGame: false)
|
return player.exchangeableCards
|
||||||
|
}
|
||||||
|
|
||||||
|
override func gameIsSelected(byPlayerAt index: Int) -> Bool {
|
||||||
|
players[index].selectsGame
|
||||||
}
|
}
|
||||||
|
|
||||||
override func play(card: Card, player name: PlayerName) -> (result: PlayerActionResult, table: ManageableTable?) {
|
override func play(card: Card, player name: PlayerName) -> (result: PlayerActionResult, table: ManageableTable?) {
|
||||||
|
Loading…
Reference in New Issue
Block a user