Skip to content

API Reference

State

skaty.game_state.GameState

Contains all the state of a specific game. State should never be directly modified by the user. Instead, state modification is left to the rule set and actions. Actions are applied/undone by directly calling their apply/undo method. The validity of actions and calculation of game score is strictly delegated to the rule set passed.

action_history: list[Action] = [] instance-attribute

List of all actions in chronological order. Should not be directly modified, because apply_action and undo_action manage it.

active_player: PlayerIdx = self._middlehand instance-attribute

Currently active player.

bid: Optional[int] = None instance-attribute

Highest bid yet.

current_trick = Trick() instance-attribute

Current trick.

game_type: Optional[GameType] = None instance-attribute

Current game type.

hand_available = True instance-attribute

Has the player looked at the skat?

hands = hands instance-attribute

List of player hands indexed with PlayerIdx.

phase: GamePhase = GamePhases.BID instance-attribute

Current game phase.

points: list[int] = [0, 0, 0] instance-attribute

Points achieved in won tricks.

skat = skat instance-attribute

List of two card Skat.

trick_history: list[Trick] = [] instance-attribute

List of all tricks in chronological order.

undo_memory: list[dict[str, Any]] = [] instance-attribute

Every action's apply method pushes a dictionary to this list with information about the previous state. This is in turn popped and used in the undo method. Index corresponds to action_history.

__init__(rule_set: AbstractRuleSet[GameState], dealer_idx: PlayerIdx, hands: list[list[Card]], skat: list[Card], log: bool = False)

Initialize a game.

Parameters:

Name Type Description Default
rule_set AbstractRuleSet[GameState]

Ruleset to consider during the game.

required
dealer_idx PlayerIdx

Index of the player who deals the hands.

required
hands list[list[Card]]

3 hands of 10 cards, with the primary index corresponding to the player's index.

required
skat list[Card]

2 cards to be buried in the Skat.

required
log bool

Whether to log information about game state to stdout.

False

Raises:

Type Description
InvalidGameStateError

If hands or skat or dealer_idx are incorrect.

apply_action(action: Action, check_validity: bool = True) -> None

Optionally check if action is valid, then call its apply method. Appends action to action_history.

calculate_game_score() -> list[int]

Wrapper for AbstractRuleSet.calculate_game_score.

from_random_deal(rule_set: AbstractRuleSet, dealer_idx: PlayerIdx, log: bool = False) -> Self classmethod

Creates a game with a randomized deck. See init for docs.

get_player_position(player_idx: PlayerIdx) -> PlayerPosition

Returns the PlayerPosition for a given player with player_idx.

get_valid_actions(player_idx: PlayerIdx) -> Iterator[Action]

Wrapper for AbstractRuleSet.get_valid_actions.

undo_action() -> None

Pops the last action from action_history and executes its undo method.

Raises:

Type Description
InvalidGameStateError

If action_history contains no action to undo.

skaty.cards.Suit

Bases: IntEnum

Suits according to ISkO 1.2.1.

CLUBS = 3 class-attribute instance-attribute

CLUBS

DIAMONDS = 0 class-attribute instance-attribute

DIAMONDS

HEARTS = 1 class-attribute instance-attribute

HEARTS

SPADES = 2 class-attribute instance-attribute

SPADES

skaty.cards.Rank

Bases: IntEnum

Rank values to differentiate the cards value. These are not to be confused with their actual points according to ISkO 1.2.2 which are returned with the points method.

points: int property

Returns the point value of the card rank in Skat (ISkO 1.2.2).

skaty.cards.Card

Card identified by rank and suit.

rank: Rank property

Rank of card.

suit: Suit property

Suit of card.

skaty.cards.create_deck() -> list[Card]

Creates an unshuffled Skat deck.

skaty.cards.shuffle_deck(deck: list[Card]) -> list[Card]

Shuffles a given deck of cards.

skaty.trick.Trick

A single trick of 3 cards.

cards: list[Card] property

Cards in trick in order.

first_card: Optional[Card] property

Returns the first card from trick if exists.

len: int property

Number of cards in trick.

add_card(card: Card)

Appends a card to the trick.

Raises:

Type Description
TrickFinishedError

If the trick is already complete.

get_trick_points() -> int

Returns the sum of all card points. The trick does not have to be completed.

get_winner(rule_set: AbstractRuleSet, game_type: GameType) -> int

Determines the winner of the trick in its order (i.e. 0 if the first card wins the trick...).

Raises:

Type Description
TrickNotFinishedError

If the trick does not contain exactly 3 cards.

is_complete()

Is trick finished?

pop() -> Optional[Card]

Returns the last card played in the trick. Returns None if trick has no cards.

Rules

Information

skaty.rules.TState = TypeVar('TState', bound='GameState') module-attribute

Any GameState.

skaty.rules.PlayerIdx = Literal[0, 1, 2]

Number to uniquely identify player in a single game.

skaty.rules.PlayerPosition

Bases: IntEnum

Position during bidding or while playing.

skaty.rules.GamePhase = NewType('GamePhase', str) module-attribute

Differentiate between GamePhases and strings for type checking. GamePhase should have form scope + ':' + IDENTIFIER (e.g. 'core:BID').

skaty.rules.GamePhases

BID = GamePhase('core:BID') class-attribute instance-attribute

Bidding phase.

DECLARATION = GamePhase('core:DECLARATION') class-attribute instance-attribute

Waiting for a player to declare or use Skat.

GAME_OVER = GamePhase('core:GAME_OVER') class-attribute instance-attribute

Game over.

PLAYING = GamePhase('core:PLAYING') class-attribute instance-attribute

Playing cards in tricks.

skaty.rules.GameType = NewType('GameType', str) module-attribute

Differentiate between GameTypes and strings for type checking. GameType should have form scope + ':' + IDENTIFIER (e.g. 'core:PASS')

skaty.rules.GameTypes

PASS = GameType('core:PASS') class-attribute instance-attribute

Used if a game is passed during bidding.

Action

skaty.rules.Action dataclass

Bases: ABC, Generic[TState]

Base class for any action.

player_idx: PlayerIdx instance-attribute

Player taking the action.

apply(state: TState, rule_set: AbstractRuleSet[TState]) -> None abstractmethod

Mutate state dependent on action type, state and rules.

is_valid(state: TState, rule_set: AbstractRuleSet[TState]) -> bool

Wrapper for rule_set.is_valid_action(state,self).

undo(state: TState) -> None abstractmethod

Reverse to state before action was applied. Restores state exactly.

Rule Set

skaty.rules.AbstractRuleSet

Bases: ABC, Generic[TState]

Base class for every rule set over a given type of state. The rule set itself is stateless. All state belongs to TState.

advance_state(state: TState, action: Action) -> None abstractmethod

Hook for rule set to change state after an action is applied (e.g. change bidding phase).

calculate_game_score(state: TState) -> list[int] abstractmethod

Attempt to calculate the game score in state. Returns a list with points (positive or negative) for each player with indexes corresponding to the state's players.

Raises:

Type Description
InvalidGameStateError

If there is no game score in the current state.

determine_trick_winner(trick: list[Card], game_type: GameType) -> int abstractmethod

Calculates index of winning player.

Parameters:

Name Type Description Default
trick list[Card]

Cards played in order of the trick.

required
game_type GameType

Game type used for trick.

required

Returns:

Type Description
PlayerIdx

Of the winning player

Raises:

Type Description
TrickNotFinishedError

If trick is not finished.

InvalidGameTypeError

If game type does not allow for tricks.

get_valid_actions(state: TState, player_idx: PlayerIdx) -> Generator[Action, None, None] abstractmethod

Yields all valid actions the player can take in state.

initialize_state(state: TState) -> None abstractmethod

Hook to initialize rule-specific attributes in state.

is_valid_action(state: TState, action: Action) -> bool abstractmethod

Checks if an action is valid in the current state.

Exceptions

skaty.exceptions

InvalidActionError

Bases: SkatyError

Raised when an illegal action is tried (e.g. acting when not being the active player).

InvalidGameStateError

Bases: SkatyError

Raised if an operation is performed in an invalid game state (e.g. playing a card before a trick starts).

InvalidGameTypeError

Bases: SkatyError

Raised when an invalid game type is passed as an argument (e.g. passing GameType.PASS for is_valid_game_declaration).

NoCardsError

Bases: SkatyError

Raised when no cards are passed where there should be some.

NoHigherBidPossible

Bases: SkatyError

Raised when no higher bid is possible according to the rules.

SkatyError

Bases: Exception

Base exception for all Skaty-related errors.

TrickFinishedError

Bases: InvalidGameStateError

Raised when a card is added to a trick if it is finished.

TrickNotFinishedError

Bases: InvalidGameStateError

Raised when a trick with less than 3 cards is probed for a winner.

ISkO

State

skaty.isko.state.BiddingPhase

Bases: IntEnum

Phase in the bidding process.

skaty.isko.state.ISkOGameTypes

Bases: GameTypes

Extending GameTypes with ISkO game types.

CLUBS = GameType('isko:clubs') class-attribute instance-attribute

CLUBS

DIAMONDS = GameType('isko:diamonds') class-attribute instance-attribute

DIAMONDS

GRAND = GameType('isko:grand') class-attribute instance-attribute

GRAND

HEARTS = GameType('isko:hearts') class-attribute instance-attribute

HEARTS

NULL = GameType('isko:null') class-attribute instance-attribute

NULL

SPADES = GameType('isko:spades') class-attribute instance-attribute

SPADES

skaty.isko.state.GameDeclaration dataclass

Everything an ISkO game declaration can contain.

game_type: GameType instance-attribute

Game type to be played.

hand: bool = False class-attribute instance-attribute

Has the declarer looked at the Skat?

open: bool = False class-attribute instance-attribute

Has the declarer announced open? In case of Null game equivalent to ouvert.

schneider: bool = False class-attribute instance-attribute

Has the declarer announced Schneider?

schwarz: bool = False class-attribute instance-attribute

Has the declarer announced Schwarz?

skaty.isko.state.ISkOGameState

Bases: GameState

Extending GameState with attributes for ISkO rules.

bid_before: list[bool] instance-attribute

Has the player with player_idx asserted a positive bid (DeclareBid or Listen) before?

bidding_phase: BiddingPhase instance-attribute

Current bidding phase.

declaration: Optional[GameDeclaration] instance-attribute

Declaration made by declarer.

declarer_idx: Optional[PlayerIdx] instance-attribute

PlayerIdx of the declarer.

last_bid: Optional[DeclareBid | Listen | Pass] instance-attribute

Last bid action to happen.

passes: list[bool] instance-attribute

Has the player with player_idx asserted a negative bid/Pass before?

tops: Optional[int] instance-attribute

Tops in declarers hand and the start of game.

tricks_won: list[int] instance-attribute

Tricks won by player with player_idx

skaty.isko.state.T_ISkOGameState = TypeVar('T_ISkOGameState', bound=ISkOGameState) module-attribute

Any GameState based on ISkOGameState.

Actions

skaty.isko.actions.DeclareBid dataclass

Bases: Action[T_ISkOGameState]

Declare bid value.

skaty.isko.actions.Listen dataclass

Bases: Action[T_ISkOGameState]

Listen during bidding phase.

skaty.isko.actions.Pass dataclass

Bases: Action[T_ISkOGameState]

Pass during bidding phase.

skaty.isko.actions.DrawSkat dataclass

Bases: Action[T_ISkOGameState]

Draw Skat into players hand, removing hand multiplier.

skaty.isko.actions.BurySkat dataclass

Bases: Action[T_ISkOGameState]

Bury cards from hand into the Skat.

skaty.isko.actions.DeclareGame dataclass

Bases: Action[T_ISkOGameState]

Declare specific game. Hand is applied automatically dependent on the game state.

skaty.isko.actions.PlayCard dataclass

Bases: Action[T_ISkOGameState]

Play specific card.

Rule Set

skaty.isko.rules.VALID_BIDS = [18, 20, 22, 23, 24, 27, 30, 33, 35, 36, 40, 44, 45, 46, 48, 50, 54, 55, 59, 60, 63, 66, 70, 72, 77, 80, 81, 84, 88, 90, 96, 99, 100, 108, 110, 117, 120, 121, 126, 130, 132, 135, 140, 143, 144, 150, 153, 154, 156, 160, 162, 165, 168, 170, 176, 180, 187, 192, 198, 204, 216, 240, 264] module-attribute

skaty.isko.rules.ISkO

Bases: AbstractRuleSet[T_ISkOGameState]

advance_bidding(state: T_ISkOGameState, action: DeclareBid | Listen | Pass) -> None

Mutate the state in bidding dependent on action. Might modify:

  • state.active_player
  • state.bidding_phase
  • state.phase
  • state.declarer_idx

If bidding continues after action, update:

  • state.active_player: to the next player bidding
  • state.bidding_phase: if a player passes

If bidding finishes with a declarer after action, update:

  • state.active_player: to be index of declarer
  • state.phase: to GamePhase.DECLARATION
  • state.declarer_idx: to be index of declarer

If bidding finishes with all players passing after action, update:

  • state.phase: to GamePhase.GAME_OVER.

advance_playing(state: T_ISkOGameState, action: PlayCard) -> None

Mutate the state as card is played. Might modify:

  • state.active_player
  • state.phase
  • state.current_trick
  • state.trick_history
  • state.points
  • state.tricks_won

advance_state(state: T_ISkOGameState, action: Action) -> None

Advance state with action. Advances bidding/active player, sets game declarations etc.

calculate_game_score(state: T_ISkOGameState) -> list[int]

Score calculation according to ISkO and docstring of base class.

determine_trick_winner(trick: list[Card], game_type: GameType) -> int

Determines the winner of the trick in its order (i.e. 0 if the first card wins the trick...).

Raises:

Type Description
TrickNotFinishedError

If trick does not contain exactly 3 cards.

InvalidGameTypeError

If game_type is GameType.PASS.

get_action_types_for_phase(phase: GamePhase) -> list[type[Action]]

Returns all valid action types for a given phase.

get_card_effective_rank_value(card: Card, game_type: GameType) -> int

Returns a value representing a cards relative strength in a game type.

Raises:

Type Description
InvalidGameTypeError

If game_type is GameType.PASS.

get_next_valid_bid(current_bid: Optional[int]) -> int

Calculates the next highest valid bid.

Raises:

Type Description
NoHigherBidPossible

If no higher bid is possible.

get_valid_actions(state: T_ISkOGameState, player_idx: PlayerIdx) -> Generator[Action, None, None]

Implement per base class docstring.

has_suit(hand: list[Card], suit: Suit) -> bool

Does the hand contain cards with suit?

has_trump(hand: list[Card], game_type: GameType) -> bool

Does the hand contain trump cards

is_card_trump(card: Card, game_type: GameType) -> bool

Is card trump?

is_valid_action(state: T_ISkOGameState, action: Action) -> bool

Can action be applied in state? Checks if player is active and per action validity according to the rules.

Raises:

Type Description
InvalidActionError

If action is not checked, because it is unknown.

is_valid_action_type_during_phase(action: Action, phase: GamePhase) -> bool

Tests if action type is possible in game phase. Does not imply the particular action itself is valid (e.g. for Bid(17), GamePhase.BIDDING it would return True, as Bid is a valid action in bidding even though Bid(17) itself is not valid).

is_valid_bid(state: T_ISkOGameState, bid: DeclareBid | Listen | Pass) -> bool

Determines if bid is valid for player in player_pos in the context of previous_bids and bidding_phase. Passing is allowed for every player in every bidding phase if they have not passed before or bid/listened before and are the only one left.

is_valid_card_play(hand: list[Card], card: Card, first_card: Optional[Card], game_type: GameType) -> bool

Determines if player can play card in a trick started with first_card in some GameType. For an empty trick, first_card is None. If game_type is GameType.PASS always returns False regardless of card and first_card.

is_valid_game_declaration(declaration: GameDeclaration) -> bool

Determines if the game declaration is formally correct. It does not check if the game satisfies the bid. A player is allowed to overbid, but will lose during score calculation.

tops(cards: list[Card], game_type: GameType) -> int

Calculates the amount of tops according to ISkO 2.3.

Raises:

Type Description
ValueError

If the cards list is empty.

InvalidGameTypeError

If game_type is GameType.NULL or GameType.PASS.

trump_suit(game_type: GameType) -> Optional[Suit]

Return trump suit for game type if exists.