cardrank

package module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2022 License: MIT Imports: 9 Imported by: 0

README

cardrank.io/cardrank

Package cardrank.io/cardrank provides a library of types, funcs, and utilities for working with playing cards, decks, and evaluating poker hands. Supports Texas Holdem, Texas Holdem Short Deck (6-plus), Omaha, Omaha Hi/Lo, Stud, and Stud Hi/Lo.

GoDoc Tests on Linux, MacOS and Windows Go Report Card

Overview

High-level types, funcs, and standardized interfaces are included in the package to deal and evaluate hands of poker, including all necessary types for representing and working with cards, card suits, card ranks, card decks, and hands of cards. Hand evaluation is achieved with pure Go implementations of common poker hand rank evaluators.

Hands of Texas Holdem, Texas Holdem Short Deck (6-Plus), Omaha, Omaha Hi/Lo, Stud, and Stud Hi/Lo are easily created and dealt using standardized interfaces and logic, with winners being easily determined and ordered.

Development of additional poker variants, including Razz and Badugi, is planned.

Using

See Go documentation.

go get cardrank.io/cardrank
Examples

Complete examples for Texas Holdem, Texas Holdem Short Deck (6-plus), Omaha, Omaha Hi/Lo, Stud, Stud Hi/Lo are available in the source repository. Further examples are available in the Go package documentation for overviews of using the package's types, funcs and interfaces.

Below are quick examples for Texas Holdem and Omaha Hi/Lo:

Texas Holdem
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"
	"time"

	"cardrank.io/cardrank"
)

func main() {
	const players = 6
	seed := time.Now().UnixNano()
	// note: use a better pseudo-random number generator
	rnd := rand.New(rand.NewSource(seed))
	pockets, board := cardrank.Holdem.Deal(rnd.Shuffle, players)
	hands := cardrank.Holdem.RankHands(pockets, board)
	fmt.Printf("------ Holdem %d ------\n", seed)
	fmt.Printf("Board:    %b\n", board)
	for i := 0; i < players; i++ {
		fmt.Printf("Player %d: %b %s %b %b\n", i+1, hands[i].Pocket(), hands[i].Description(), hands[i].Best(), hands[i].Unused())
	}
	h, pivot := cardrank.Order(hands)
	if pivot == 1 {
		fmt.Printf("Result:   Player %d wins with %s %b\n", h[0]+1, hands[h[0]].Description(), hands[h[0]].Best())
	} else {
		var s, b []string
		for j := 0; j < pivot; j++ {
			s = append(s, strconv.Itoa(h[j]+1))
			b = append(b, fmt.Sprintf("%b", hands[h[j]].Best()))
		}
		fmt.Printf("Result:   Players %s push with %s %s\n", strings.Join(s, ", "), hands[h[0]].Description(), strings.Join(b, ", "))
	}
}
Omaha Hi/Lo
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"
	"time"

	"cardrank.io/cardrank"
)

func main() {
	const players = 6
	seed := time.Now().UnixNano()
	// note: use a better pseudo-random number generator
	rnd := rand.New(rand.NewSource(seed))
	pockets, board := cardrank.OmahaHiLo.Deal(rnd.Shuffle, players)
	hands := cardrank.OmahaHiLo.RankHands(pockets, board)
	fmt.Printf("------ OmahaHiLo %d ------\n", seed)
	fmt.Printf("Board: %b\n", board)
	for i := 0; i < players; i++ {
		fmt.Printf("Player %d: %b\n", i+1, pockets[i])
		fmt.Printf("  Hi: %s %b %b\n", hands[i].Description(), hands[i].Best(), hands[i].Unused())
		if hands[i].LowValid() {
			fmt.Printf("  Lo: %s %b %b\n", hands[i].LowDescription(), hands[i].LowBest(), hands[i].LowUnused())
		} else {
			fmt.Printf("  Lo: None\n")
		}
	}
	h, hPivot := cardrank.Order(hands)
	l, lPivot := cardrank.LowOrder(hands)
	typ := "wins"
	if lPivot == 0 {
		typ = "scoops"
	}
	if hPivot == 1 {
		fmt.Printf("Result (Hi): Player %d %s with %s %b\n", h[0]+1, typ, hands[h[0]].Description(), hands[h[0]].Best())
	} else {
		var s, b []string
		for i := 0; i < hPivot; i++ {
			s = append(s, strconv.Itoa(h[i]+1))
			b = append(b, fmt.Sprintf("%b", hands[h[i]].Best()))
		}
		fmt.Printf("Result (Hi): Players %s push with %s %s\n", strings.Join(s, ", "), hands[h[0]].Description(), strings.Join(b, ", "))
	}
	if lPivot == 1 {
		fmt.Printf("Result (Lo): Player %d wins with %s %b\n", l[0]+1, hands[l[0]].LowDescription(), hands[l[0]].LowBest())
	} else if lPivot > 1 {
		var s, b []string
		for j := 0; j < lPivot; j++ {
			s = append(s, strconv.Itoa(l[j]+1))
			b = append(b, fmt.Sprintf("%b", hands[l[j]].LowBest()))
		}
		fmt.Printf("Result (Lo): Players %s push with %s %s\n", strings.Join(s, ", "), hands[l[0]].LowDescription(), strings.Join(b, ", "))
	} else {
		fmt.Printf("Result (Lo): no player made a low hand\n")
	}
}
Hand Ranking

A HandRank type is used to determine the relative rank of a Hand, on a low-to-high basis. Higher hands will have a lower value than low hands. For example, a Straight Flush will have a lower HandRank than Full House.

Rankers

For regular poker hands (ie, Holdem, Omaha, and Stud), pure Go implementations for the well-known Cactus Kev (CactusRanker), Fast Cactus (CactusFastRanker), and Two-Plus (TwoPlusRanker) poker hand evaluators are provided. Additionally a SixPlusRanker and a EightOrBetterRanker rankers are provided, used for Short Deck and Omaha/Stud Lo evaluation respectively.

Default and Hybrid Rankers

The package's DefaultRanker is a HybridRanker using either the CactusFastRanker or TwoPlusRanker depending on the Hand having 5, 6, or 7 cards. The HybridRanker provides the best possible evaluation speed in most cases.

Ordering and Winner Determination

Hands can be compared to each other using Compare or can be ordered using the package level Order and LowOrder funcs. See the examples for overviews on winner determination.

Build Tags

Package level build tags are used to change the build configuration of the package:

portable

The portable build tag can be used to disable the TwoPlusRanker, which requires embedding a large (approximately 130 Mib) look-up table.

This is useful when using this package in a portable or embedded application. For example, when targetting a WASM build, the following can be used to create slimmer WASM binaries:

GOOS=js GOARCH=wasm go build -tags portable
embedded

The embedded tag can be used to disable the CactusFastRanker and the TwoPlusRanker, creating the smallest possible binaries:

GOOS=js GOARCH=wasm go build -tags embedded
noinit

The noinit tag enables a slightly faster startup time by disabling initialization of package level variables DefaultRanker and DefaultSixPlusRanker until needed.

GOOS=js GOARCH=wasm go build -tags 'embedded noinit'

When using the noinit build tag, the user will need to manually set the DefaultRanker and DefaultSixPlusRanker variables:

cardrank.DefaultRanker = cardrank.HandRanker(cardrank.CactusRanker)
cardrank.DefaultSixPlusRanker = cardrank.HandRanker(cardrank.SixPlusRanker(cardrank.CactusRanker))

See z.go for initialization logic.

Development Status

A partially complete Razz ranker is available, however it currently does not work with hands having a set (i.e., pair, two pair, three-of-a-kind, full house, or four-of-a-kind).

Future

Rankers for Badugi and other poker variants will be added to this package in addition to standardized interfaces for managing poker tables and games.

Documentation

Overview

Package `cardrank` provides a library of types, funcs, and utilities for working with playing cards, decks, and evaluating poker hands.

Supports Texas Holdem, Texas Holdem Short Deck (6-plus), Omaha, Omaha Hi/Lo, Stud, and Stud Hi/Lo.

Example (Holdem)
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"

	"cardrank.io/cardrank"
)

func main() {
	for i, game := range []struct {
		seed    int64
		players int
	}{
		{3, 2},
		{278062, 2},
		{1928, 6},
		{6151, 6},
		{5680, 6},
		{23965, 2},
		{13959, 2},
		{23366, 6},
		{29555, 3},
		{472600, 3},
		{107, 10},
	} {
		// note: use a real random source
		rnd := rand.New(rand.NewSource(game.seed))
		pockets, board := cardrank.Holdem.Deal(rnd.Shuffle, game.players)
		hands := cardrank.Holdem.RankHands(pockets, board)
		fmt.Printf("------ Holdem %d ------\n", i+1)
		fmt.Printf("Board:    %b\n", board)
		for j := 0; j < game.players; j++ {
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, hands[j].Pocket(), hands[j].Description(), hands[j].Best(), hands[j].Unused())
		}
		h, pivot := cardrank.Order(hands)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s %b\n", h[0]+1, hands[h[0]].Description(), hands[h[0]].Best())
		} else {
			var s, b []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(h[j]+1))
				b = append(b, fmt.Sprintf("%b", hands[h[j]].Best()))
			}
			fmt.Printf("Result:   Players %s push with %s %s\n", strings.Join(s, ", "), hands[h[0]].Description(), strings.Join(b, ", "))
		}
	}
}
Output:

------ Holdem 1 ------
Board:    [J♠ T♠ 2♦ 2♠ Q♥]
Player 1: [6♦ 8♠] Pair, Twos, kickers Queen, Jack, Ten [2♦ 2♠ Q♥ J♠ T♠] [8♠ 6♦]
Player 2: [7♠ 4♣] Pair, Twos, kickers Queen, Jack, Ten [2♦ 2♠ Q♥ J♠ T♠] [7♠ 4♣]
Result:   Players 1, 2 push with Pair, Twos, kickers Queen, Jack, Ten [2♦ 2♠ Q♥ J♠ T♠], [2♦ 2♠ Q♥ J♠ T♠]
------ Holdem 2 ------
Board:    [8♠ 9♠ J♠ 9♣ T♠]
Player 1: [7♠ T♣] Straight Flush, Jack-high [J♠ T♠ 9♠ 8♠ 7♠] [T♣ 9♣]
Player 2: [6♦ Q♠] Straight Flush, Queen-high [Q♠ J♠ T♠ 9♠ 8♠] [9♣ 6♦]
Result:   Player 2 wins with Straight Flush, Queen-high [Q♠ J♠ T♠ 9♠ 8♠]
------ Holdem 3 ------
Board:    [A♠ T♣ K♠ J♣ 6♥]
Player 1: [T♥ 2♠] Pair, Tens, kickers Ace, King, Jack [T♣ T♥ A♠ K♠ J♣] [6♥ 2♠]
Player 2: [Q♣ J♠] Straight, Ace-high [A♠ K♠ Q♣ J♣ T♣] [J♠ 6♥]
Player 3: [4♥ Q♠] Straight, Ace-high [A♠ K♠ Q♠ J♣ T♣] [6♥ 4♥]
Player 4: [5♦ K♦] Pair, Kings, kickers Ace, Jack, Ten [K♦ K♠ A♠ J♣ T♣] [6♥ 5♦]
Player 5: [Q♥ 7♣] Straight, Ace-high [A♠ K♠ Q♥ J♣ T♣] [7♣ 6♥]
Player 6: [6♠ 3♣] Pair, Sixes, kickers Ace, King, Jack [6♥ 6♠ A♠ K♠ J♣] [T♣ 3♣]
Result:   Players 2, 3, 5 push with Straight, Ace-high [A♠ K♠ Q♣ J♣ T♣], [A♠ K♠ Q♠ J♣ T♣], [A♠ K♠ Q♥ J♣ T♣]
------ Holdem 4 ------
Board:    [9♦ J♣ A♥ 9♥ J♠]
Player 1: [K♠ 7♦] Two Pair, Jacks over Nines, kicker Ace [J♣ J♠ 9♦ 9♥ A♥] [K♠ 7♦]
Player 2: [A♦ 4♥] Two Pair, Aces over Jacks, kicker Nine [A♦ A♥ J♣ J♠ 9♦] [9♥ 4♥]
Player 3: [3♥ T♣] Two Pair, Jacks over Nines, kicker Ace [J♣ J♠ 9♦ 9♥ A♥] [T♣ 3♥]
Player 4: [8♦ 9♠] Full House, Nines full of Jacks [9♦ 9♥ 9♠ J♣ J♠] [A♥ 8♦]
Player 5: [8♥ 6♣] Two Pair, Jacks over Nines, kicker Ace [J♣ J♠ 9♦ 9♥ A♥] [8♥ 6♣]
Player 6: [5♥ J♦] Full House, Jacks full of Nines [J♣ J♦ J♠ 9♦ 9♥] [A♥ 5♥]
Result:   Player 6 wins with Full House, Jacks full of Nines [J♣ J♦ J♠ 9♦ 9♥]
------ Holdem 5 ------
Board:    [3♠ 9♥ A♦ 6♥ Q♦]
Player 1: [T♦ 8♦] Nothing, Ace-high, kickers Queen, Ten, Nine, Eight [A♦ Q♦ T♦ 9♥ 8♦] [6♥ 3♠]
Player 2: [K♠ T♣] Nothing, Ace-high, kickers King, Queen, Ten, Nine [A♦ K♠ Q♦ T♣ 9♥] [6♥ 3♠]
Player 3: [7♥ 8♣] Nothing, Ace-high, kickers Queen, Nine, Eight, Seven [A♦ Q♦ 9♥ 8♣ 7♥] [6♥ 3♠]
Player 4: [4♥ 7♦] Nothing, Ace-high, kickers Queen, Nine, Seven, Six [A♦ Q♦ 9♥ 7♦ 6♥] [4♥ 3♠]
Player 5: [K♥ 5♦] Nothing, Ace-high, kickers King, Queen, Nine, Six [A♦ K♥ Q♦ 9♥ 6♥] [5♦ 3♠]
Player 6: [T♥ 5♣] Nothing, Ace-high, kickers Queen, Ten, Nine, Six [A♦ Q♦ T♥ 9♥ 6♥] [5♣ 3♠]
Result:   Player 2 wins with Nothing, Ace-high, kickers King, Queen, Ten, Nine [A♦ K♠ Q♦ T♣ 9♥]
------ Holdem 6 ------
Board:    [T♥ 6♥ 7♥ 2♥ 7♣]
Player 1: [6♣ 6♠] Full House, Sixes full of Sevens [6♣ 6♥ 6♠ 7♣ 7♥] [T♥ 2♥]
Player 2: [K♥ 5♥] Flush, King-high [K♥ T♥ 7♥ 6♥ 5♥] [2♥ 7♣]
Result:   Player 1 wins with Full House, Sixes full of Sevens [6♣ 6♥ 6♠ 7♣ 7♥]
------ Holdem 7 ------
Board:    [4♦ A♥ A♣ 4♠ A♦]
Player 1: [T♥ T♠] Full House, Aces full of Tens [A♣ A♦ A♥ T♥ T♠] [4♦ 4♠]
Player 2: [9♣ A♠] Four of a Kind, Aces, kicker Four [A♣ A♦ A♥ A♠ 4♦] [4♠ 9♣]
Result:   Player 2 wins with Four of a Kind, Aces, kicker Four [A♣ A♦ A♥ A♠ 4♦]
------ Holdem 8 ------
Board:    [Q♥ T♥ T♠ J♥ K♥]
Player 1: [A♥ 9♠] Straight Flush, Ace-high, Royal [A♥ K♥ Q♥ J♥ T♥] [T♠ 9♠]
Player 2: [Q♣ 2♠] Two Pair, Queens over Tens, kicker King [Q♣ Q♥ T♥ T♠ K♥] [J♥ 2♠]
Player 3: [6♥ 3♦] Flush, King-high [K♥ Q♥ J♥ T♥ 6♥] [T♠ 3♦]
Player 4: [8♥ 8♦] Flush, King-high [K♥ Q♥ J♥ T♥ 8♥] [T♠ 8♦]
Player 5: [4♦ Q♦] Two Pair, Queens over Tens, kicker King [Q♦ Q♥ T♥ T♠ K♥] [J♥ 4♦]
Player 6: [A♦ T♣] Straight, Ace-high [A♦ K♥ Q♥ J♥ T♣] [T♥ T♠]
Result:   Player 1 wins with Straight Flush, Ace-high, Royal [A♥ K♥ Q♥ J♥ T♥]
------ Holdem 9 ------
Board:    [A♣ 2♣ 4♣ 5♣ 9♥]
Player 1: [T♣ J♦] Flush, Ace-high [A♣ T♣ 5♣ 4♣ 2♣] [J♦ 9♥]
Player 2: [4♥ 6♠] Pair, Fours, kickers Ace, Nine, Six [4♣ 4♥ A♣ 9♥ 6♠] [5♣ 2♣]
Player 3: [3♣ T♠] Straight Flush, Five-high, Steel Wheel [5♣ 4♣ 3♣ 2♣ A♣] [T♠ 9♥]
Result:   Player 3 wins with Straight Flush, Five-high, Steel Wheel [5♣ 4♣ 3♣ 2♣ A♣]
------ Holdem 10 ------
Board:    [8♣ J♣ 8♥ 7♥ 9♥]
Player 1: [8♦ 8♠] Four of a Kind, Eights, kicker Jack [8♣ 8♦ 8♥ 8♠ J♣] [9♥ 7♥]
Player 2: [6♥ T♥] Straight Flush, Ten-high [T♥ 9♥ 8♥ 7♥ 6♥] [J♣ 8♣]
Player 3: [3♣ K♥] Pair, Eights, kickers King, Jack, Nine [8♣ 8♥ K♥ J♣ 9♥] [7♥ 3♣]
Result:   Player 2 wins with Straight Flush, Ten-high [T♥ 9♥ 8♥ 7♥ 6♥]
------ Holdem 11 ------
Board:    [5♥ 3♣ J♥ 6♦ 6♣]
Player 1: [8♥ 4♥] Pair, Sixes, kickers Jack, Eight, Five [6♣ 6♦ J♥ 8♥ 5♥] [4♥ 3♣]
Player 2: [T♣ 3♥] Two Pair, Sixes over Threes, kicker Jack [6♣ 6♦ 3♣ 3♥ J♥] [T♣ 5♥]
Player 3: [A♠ 6♠] Three of a Kind, Sixes, kickers Ace, Jack [6♣ 6♦ 6♠ A♠ J♥] [5♥ 3♣]
Player 4: [J♠ 8♠] Two Pair, Jacks over Sixes, kicker Eight [J♥ J♠ 6♣ 6♦ 8♠] [5♥ 3♣]
Player 5: [6♥ 2♣] Three of a Kind, Sixes, kickers Jack, Five [6♣ 6♦ 6♥ J♥ 5♥] [3♣ 2♣]
Player 6: [T♥ Q♣] Pair, Sixes, kickers Queen, Jack, Ten [6♣ 6♦ Q♣ J♥ T♥] [5♥ 3♣]
Player 7: [Q♠ 5♦] Two Pair, Sixes over Fives, kicker Queen [6♣ 6♦ 5♦ 5♥ Q♠] [J♥ 3♣]
Player 8: [T♠ 2♠] Pair, Sixes, kickers Jack, Ten, Five [6♣ 6♦ J♥ T♠ 5♥] [3♣ 2♠]
Player 9: [5♣ 9♦] Two Pair, Sixes over Fives, kicker Jack [6♣ 6♦ 5♣ 5♥ J♥] [9♦ 3♣]
Player 10: [J♣ A♣] Two Pair, Jacks over Sixes, kicker Ace [J♣ J♥ 6♣ 6♦ A♣] [5♥ 3♣]
Result:   Player 3 wins with Three of a Kind, Sixes, kickers Ace, Jack [6♣ 6♦ 6♠ A♠ J♥]
Example (Omaha)
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"

	"cardrank.io/cardrank"
)

func main() {
	for i, game := range []struct {
		seed    int64
		players int
	}{
		{119, 2},
		{321, 5},
		{408, 6},
		{455, 6},
		{1113, 6},
	} {
		// note: use a real random source
		rnd := rand.New(rand.NewSource(game.seed))
		pockets, board := cardrank.Omaha.Deal(rnd.Shuffle, game.players)
		hands := cardrank.Omaha.RankHands(pockets, board)
		fmt.Printf("------ Omaha %d ------\n", i+1)
		fmt.Printf("Board:    %b\n", board)
		for j := 0; j < game.players; j++ {
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, hands[j].Pocket(), hands[j].Description(), hands[j].Best(), hands[j].Unused())
		}
		h, pivot := cardrank.Order(hands)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s %b\n", h[0]+1, hands[h[0]].Description(), hands[h[0]].Best())
		} else {
			var s, b []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(h[j]+1))
				b = append(b, fmt.Sprintf("%b", hands[h[j]].Best()))
			}
			fmt.Printf("Result:   Players %s push with %s %s\n", strings.Join(s, ", "), hands[h[0]].Description(), strings.Join(b, ", "))
		}
	}
}
Output:

------ Omaha 1 ------
Board:    [3♥ 5♥ 4♥ 7♥ K♣]
Player 1: [K♥ 7♣ J♣ 4♣] Two Pair, Kings over Sevens, kicker Five [K♣ K♥ 7♣ 7♥ 5♥] [J♣ 4♣ 3♥ 4♥]
Player 2: [A♥ 5♠ Q♠ 2♠] Straight, Five-high [5♥ 4♥ 3♥ 2♠ A♥] [5♠ Q♠ 7♥ K♣]
Result:   Player 2 wins with Straight, Five-high [5♥ 4♥ 3♥ 2♠ A♥]
------ Omaha 2 ------
Board:    [3♥ 7♣ 3♣ 9♠ 9♣]
Player 1: [3♠ 6♦ Q♦ K♦] Three of a Kind, Threes, kickers King, Nine [3♣ 3♥ 3♠ K♦ 9♠] [6♦ Q♦ 7♣ 9♣]
Player 2: [J♦ 3♦ Q♣ K♠] Three of a Kind, Threes, kickers King, Nine [3♣ 3♦ 3♥ K♠ 9♠] [J♦ Q♣ 7♣ 9♣]
Player 3: [T♦ 2♥ T♠ 8♥] Two Pair, Tens over Nines, kicker Seven [T♦ T♠ 9♣ 9♠ 7♣] [2♥ 8♥ 3♥ 3♣]
Player 4: [8♣ 8♦ Q♥ Q♠] Two Pair, Queens over Nines, kicker Seven [Q♥ Q♠ 9♣ 9♠ 7♣] [8♣ 8♦ 3♥ 3♣]
Player 5: [6♣ A♥ 4♥ 6♠] Two Pair, Nines over Sixes, kicker Seven [9♣ 9♠ 6♣ 6♠ 7♣] [A♥ 4♥ 3♥ 3♣]
Result:   Players 1, 2 push with Three of a Kind, Threes, kickers King, Nine [3♣ 3♥ 3♠ K♦ 9♠], [3♣ 3♦ 3♥ K♠ 9♠]
------ Omaha 3 ------
Board:    [J♣ T♥ 4♥ K♣ Q♣]
Player 1: [K♠ J♠ 3♠ 5♣] Two Pair, Kings over Jacks, kicker Queen [K♣ K♠ J♣ J♠ Q♣] [3♠ 5♣ T♥ 4♥]
Player 2: [7♠ 4♠ Q♠ 3♣] Two Pair, Queens over Fours, kicker King [Q♣ Q♠ 4♥ 4♠ K♣] [7♠ 3♣ J♣ T♥]
Player 3: [T♠ 5♥ 3♥ 8♦] Pair, Tens, kickers King, Queen, Eight [T♥ T♠ K♣ Q♣ 8♦] [5♥ 3♥ J♣ 4♥]
Player 4: [4♣ 8♥ 2♣ T♦] Flush, King-high [K♣ Q♣ J♣ 4♣ 2♣] [8♥ T♦ T♥ 4♥]
Player 5: [6♠ K♦ J♦ 2♠] Two Pair, Kings over Jacks, kicker Queen [K♣ K♦ J♣ J♦ Q♣] [6♠ 2♠ T♥ 4♥]
Player 6: [Q♦ 2♦ A♣ T♣] Straight Flush, Ace-high, Royal [A♣ K♣ Q♣ J♣ T♣] [Q♦ 2♦ T♥ 4♥]
Result:   Player 6 wins with Straight Flush, Ace-high, Royal [A♣ K♣ Q♣ J♣ T♣]
------ Omaha 4 ------
Board:    [2♦ 6♦ 6♣ Q♣ 7♣]
Player 1: [6♠ Q♥ 2♣ 9♠] Full House, Sixes full of Queens [6♣ 6♦ 6♠ Q♣ Q♥] [2♣ 9♠ 2♦ 7♣]
Player 2: [3♦ T♣ K♥ 4♥] Pair, Sixes, kickers King, Queen, Ten [6♣ 6♦ K♥ Q♣ T♣] [3♦ 4♥ 2♦ 7♣]
Player 3: [6♥ J♥ 4♦ Q♦] Full House, Sixes full of Queens [6♣ 6♦ 6♥ Q♣ Q♦] [J♥ 4♦ 2♦ 7♣]
Player 4: [A♣ J♣ 5♣ K♠] Flush, Ace-high [A♣ Q♣ J♣ 7♣ 6♣] [5♣ K♠ 2♦ 6♦]
Player 5: [K♣ A♠ 8♣ 5♥] Flush, King-high [K♣ Q♣ 8♣ 7♣ 6♣] [A♠ 5♥ 2♦ 6♦]
Player 6: [Q♠ J♠ 8♦ 7♥] Two Pair, Queens over Sevens, kicker Six [Q♣ Q♠ 7♣ 7♥ 6♦] [J♠ 8♦ 2♦ 6♣]
Result:   Players 1, 3 push with Full House, Sixes full of Queens [6♣ 6♦ 6♠ Q♣ Q♥], [6♣ 6♦ 6♥ Q♣ Q♦]
------ Omaha 5 ------
Board:    [4♣ K♣ 6♦ 9♦ 5♠]
Player 1: [3♦ T♥ A♣ 7♦] Straight, Seven-high [7♦ 6♦ 5♠ 4♣ 3♦] [T♥ A♣ K♣ 9♦]
Player 2: [5♣ 6♠ 4♦ J♠] Two Pair, Sixes over Fives, kicker King [6♦ 6♠ 5♣ 5♠ K♣] [4♦ J♠ 4♣ 9♦]
Player 3: [9♠ 3♣ Q♠ 7♠] Straight, Seven-high [7♠ 6♦ 5♠ 4♣ 3♣] [9♠ Q♠ K♣ 9♦]
Player 4: [5♦ K♠ T♠ 8♠] Two Pair, Kings over Fives, kicker Nine [K♣ K♠ 5♦ 5♠ 9♦] [T♠ 8♠ 4♣ 6♦]
Player 5: [J♥ 7♥ J♣ 2♣] Pair, Jacks, kickers King, Nine, Six [J♣ J♥ K♣ 9♦ 6♦] [7♥ 2♣ 4♣ 5♠]
Player 6: [3♠ 7♣ 2♠ 2♥] Straight, Seven-high [7♣ 6♦ 5♠ 4♣ 3♠] [2♠ 2♥ K♣ 9♦]
Result:   Players 1, 3, 6 push with Straight, Seven-high [7♦ 6♦ 5♠ 4♣ 3♦], [7♠ 6♦ 5♠ 4♣ 3♣], [7♣ 6♦ 5♠ 4♣ 3♠]
Example (OmahaHiLo)
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"

	"cardrank.io/cardrank"
)

func main() {
	for i, game := range []struct {
		seed    int64
		players int
	}{
		{119, 2},
		{321, 5},
		{408, 6},
		{455, 6},
		{1113, 6},
	} {
		// note: use a real random source
		rnd := rand.New(rand.NewSource(game.seed))
		pockets, board := cardrank.OmahaHiLo.Deal(rnd.Shuffle, game.players)
		hands := cardrank.OmahaHiLo.RankHands(pockets, board)
		fmt.Printf("------ OmahaHiLo %d ------\n", i+1)
		fmt.Printf("Board: %b\n", board)
		for j := 0; j < game.players; j++ {
			fmt.Printf("Player %d: %b\n", j+1, pockets[j])
			fmt.Printf("  Hi: %s %b %b\n", hands[j].Description(), hands[j].Best(), hands[j].Unused())
			if hands[j].LowValid() {
				fmt.Printf("  Lo: %s %b %b\n", hands[j].LowDescription(), hands[j].LowBest(), hands[j].LowUnused())
			} else {
				fmt.Printf("  Lo: None\n")
			}
		}
		h, hPivot := cardrank.Order(hands)
		l, lPivot := cardrank.LowOrder(hands)
		typ := "wins"
		if lPivot == 0 {
			typ = "scoops"
		}
		if hPivot == 1 {
			fmt.Printf("Result (Hi): Player %d %s with %s %b\n", h[0]+1, typ, hands[h[0]].Description(), hands[h[0]].Best())
		} else {
			var s, b []string
			for j := 0; j < hPivot; j++ {
				s = append(s, strconv.Itoa(h[j]+1))
				b = append(b, fmt.Sprintf("%b", hands[h[j]].Best()))
			}
			fmt.Printf("Result (Hi): Players %s push with %s %s\n", strings.Join(s, ", "), hands[h[0]].Description(), strings.Join(b, ", "))
		}
		if lPivot == 1 {
			fmt.Printf("Result (Lo): Player %d wins with %s %b\n", l[0]+1, hands[l[0]].LowDescription(), hands[l[0]].LowBest())
		} else if lPivot > 1 {
			var s, b []string
			for j := 0; j < lPivot; j++ {
				s = append(s, strconv.Itoa(l[j]+1))
				b = append(b, fmt.Sprintf("%b", hands[l[j]].LowBest()))
			}
			fmt.Printf("Result (Lo): Players %s push with %s %s\n", strings.Join(s, ", "), hands[l[0]].LowDescription(), strings.Join(b, ", "))
		} else {
			fmt.Printf("Result (Lo): no player made a low hand\n")
		}
	}
}
Output:

------ OmahaHiLo 1 ------
Board: [3♥ 5♥ 4♥ 7♥ K♣]
Player 1: [K♥ 7♣ J♣ 4♣]
  Hi: Two Pair, Kings over Sevens, kicker Five [K♣ K♥ 7♣ 7♥ 5♥] [J♣ 4♣ 3♥ 4♥]
  Lo: None
Player 2: [A♥ 5♠ Q♠ 2♠]
  Hi: Straight, Five-high [5♥ 4♥ 3♥ 2♠ A♥] [5♠ Q♠ 7♥ K♣]
  Lo: Five-low [5♥ 4♥ 3♥ 2♠ A♥] [5♠ Q♠ 7♥ K♣]
Result (Hi): Player 2 wins with Straight, Five-high [5♥ 4♥ 3♥ 2♠ A♥]
Result (Lo): Player 2 wins with Five-low [5♥ 4♥ 3♥ 2♠ A♥]
------ OmahaHiLo 2 ------
Board: [3♥ 7♣ 3♣ 9♠ 9♣]
Player 1: [3♠ 6♦ Q♦ K♦]
  Hi: Three of a Kind, Threes, kickers King, Nine [3♣ 3♥ 3♠ K♦ 9♠] [6♦ Q♦ 7♣ 9♣]
  Lo: None
Player 2: [J♦ 3♦ Q♣ K♠]
  Hi: Three of a Kind, Threes, kickers King, Nine [3♣ 3♦ 3♥ K♠ 9♠] [J♦ Q♣ 7♣ 9♣]
  Lo: None
Player 3: [T♦ 2♥ T♠ 8♥]
  Hi: Two Pair, Tens over Nines, kicker Seven [T♦ T♠ 9♣ 9♠ 7♣] [2♥ 8♥ 3♥ 3♣]
  Lo: None
Player 4: [8♣ 8♦ Q♥ Q♠]
  Hi: Two Pair, Queens over Nines, kicker Seven [Q♥ Q♠ 9♣ 9♠ 7♣] [8♣ 8♦ 3♥ 3♣]
  Lo: None
Player 5: [6♣ A♥ 4♥ 6♠]
  Hi: Two Pair, Nines over Sixes, kicker Seven [9♣ 9♠ 6♣ 6♠ 7♣] [A♥ 4♥ 3♥ 3♣]
  Lo: None
Result (Hi): Players 1, 2 push with Three of a Kind, Threes, kickers King, Nine [3♣ 3♥ 3♠ K♦ 9♠], [3♣ 3♦ 3♥ K♠ 9♠]
Result (Lo): no player made a low hand
------ OmahaHiLo 3 ------
Board: [J♣ T♥ 4♥ K♣ Q♣]
Player 1: [K♠ J♠ 3♠ 5♣]
  Hi: Two Pair, Kings over Jacks, kicker Queen [K♣ K♠ J♣ J♠ Q♣] [3♠ 5♣ T♥ 4♥]
  Lo: None
Player 2: [7♠ 4♠ Q♠ 3♣]
  Hi: Two Pair, Queens over Fours, kicker King [Q♣ Q♠ 4♥ 4♠ K♣] [7♠ 3♣ J♣ T♥]
  Lo: None
Player 3: [T♠ 5♥ 3♥ 8♦]
  Hi: Pair, Tens, kickers King, Queen, Eight [T♥ T♠ K♣ Q♣ 8♦] [5♥ 3♥ J♣ 4♥]
  Lo: None
Player 4: [4♣ 8♥ 2♣ T♦]
  Hi: Flush, King-high [K♣ Q♣ J♣ 4♣ 2♣] [8♥ T♦ T♥ 4♥]
  Lo: None
Player 5: [6♠ K♦ J♦ 2♠]
  Hi: Two Pair, Kings over Jacks, kicker Queen [K♣ K♦ J♣ J♦ Q♣] [6♠ 2♠ T♥ 4♥]
  Lo: None
Player 6: [Q♦ 2♦ A♣ T♣]
  Hi: Straight Flush, Ace-high, Royal [A♣ K♣ Q♣ J♣ T♣] [Q♦ 2♦ T♥ 4♥]
  Lo: None
Result (Hi): Player 6 scoops with Straight Flush, Ace-high, Royal [A♣ K♣ Q♣ J♣ T♣]
Result (Lo): no player made a low hand
------ OmahaHiLo 4 ------
Board: [2♦ 6♦ 6♣ Q♣ 7♣]
Player 1: [6♠ Q♥ 2♣ 9♠]
  Hi: Full House, Sixes full of Queens [6♣ 6♦ 6♠ Q♣ Q♥] [2♣ 9♠ 2♦ 7♣]
  Lo: None
Player 2: [3♦ T♣ K♥ 4♥]
  Hi: Pair, Sixes, kickers King, Queen, Ten [6♣ 6♦ K♥ Q♣ T♣] [3♦ 4♥ 2♦ 7♣]
  Lo: Seven-low [7♣ 6♦ 4♥ 3♦ 2♦] [T♣ K♥ 6♣ Q♣]
Player 3: [6♥ J♥ 4♦ Q♦]
  Hi: Full House, Sixes full of Queens [6♣ 6♦ 6♥ Q♣ Q♦] [J♥ 4♦ 2♦ 7♣]
  Lo: None
Player 4: [A♣ J♣ 5♣ K♠]
  Hi: Flush, Ace-high [A♣ Q♣ J♣ 7♣ 6♣] [5♣ K♠ 2♦ 6♦]
  Lo: Seven-low [7♣ 6♦ 5♣ 2♦ A♣] [J♣ K♠ 6♣ Q♣]
Player 5: [K♣ A♠ 8♣ 5♥]
  Hi: Flush, King-high [K♣ Q♣ 8♣ 7♣ 6♣] [A♠ 5♥ 2♦ 6♦]
  Lo: Seven-low [7♣ 6♦ 5♥ 2♦ A♠] [K♣ 8♣ 6♣ Q♣]
Player 6: [Q♠ J♠ 8♦ 7♥]
  Hi: Two Pair, Queens over Sevens, kicker Six [Q♣ Q♠ 7♣ 7♥ 6♦] [J♠ 8♦ 2♦ 6♣]
  Lo: None
Result (Hi): Players 1, 3 push with Full House, Sixes full of Queens [6♣ 6♦ 6♠ Q♣ Q♥], [6♣ 6♦ 6♥ Q♣ Q♦]
Result (Lo): Player 2 wins with Seven-low [7♣ 6♦ 4♥ 3♦ 2♦]
------ OmahaHiLo 5 ------
Board: [4♣ K♣ 6♦ 9♦ 5♠]
Player 1: [3♦ T♥ A♣ 7♦]
  Hi: Straight, Seven-high [7♦ 6♦ 5♠ 4♣ 3♦] [T♥ A♣ K♣ 9♦]
  Lo: Six-low [6♦ 5♠ 4♣ 3♦ A♣] [T♥ 7♦ K♣ 9♦]
Player 2: [5♣ 6♠ 4♦ J♠]
  Hi: Two Pair, Sixes over Fives, kicker King [6♦ 6♠ 5♣ 5♠ K♣] [4♦ J♠ 4♣ 9♦]
  Lo: None
Player 3: [9♠ 3♣ Q♠ 7♠]
  Hi: Straight, Seven-high [7♠ 6♦ 5♠ 4♣ 3♣] [9♠ Q♠ K♣ 9♦]
  Lo: Seven-low [7♠ 6♦ 5♠ 4♣ 3♣] [9♠ Q♠ K♣ 9♦]
Player 4: [5♦ K♠ T♠ 8♠]
  Hi: Two Pair, Kings over Fives, kicker Nine [K♣ K♠ 5♦ 5♠ 9♦] [T♠ 8♠ 4♣ 6♦]
  Lo: None
Player 5: [J♥ 7♥ J♣ 2♣]
  Hi: Pair, Jacks, kickers King, Nine, Six [J♣ J♥ K♣ 9♦ 6♦] [7♥ 2♣ 4♣ 5♠]
  Lo: Seven-low [7♥ 6♦ 5♠ 4♣ 2♣] [J♥ J♣ K♣ 9♦]
Player 6: [3♠ 7♣ 2♠ 2♥]
  Hi: Straight, Seven-high [7♣ 6♦ 5♠ 4♣ 3♠] [2♠ 2♥ K♣ 9♦]
  Lo: Six-low [6♦ 5♠ 4♣ 3♠ 2♠] [7♣ 2♥ K♣ 9♦]
Result (Hi): Players 1, 3, 6 push with Straight, Seven-high [7♦ 6♦ 5♠ 4♣ 3♦], [7♠ 6♦ 5♠ 4♣ 3♣], [7♣ 6♦ 5♠ 4♣ 3♠]
Result (Lo): Player 1 wins with Six-low [6♦ 5♠ 4♣ 3♦ A♣]
Example (Razz)
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"

	"cardrank.io/cardrank"
)

func main() {
	// not currently working
	return
	for i, game := range []struct {
		seed    int64
		players int
	}{
		{119, 2},
		{321, 5},
		{408, 6},
		{455, 6},
		{1113, 6},
	} {
		// note: use a real random source
		rnd := rand.New(rand.NewSource(game.seed))
		pockets, _ := cardrank.Razz.Deal(rnd.Shuffle, game.players)
		hands := cardrank.Razz.RankHands(pockets, nil)
		fmt.Printf("------ Razz %d ------\n", i+1)
		for j := 0; j < game.players; j++ {
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, hands[j].Pocket(), hands[j].Description(), hands[j].Best(), hands[j].Unused())
		}
		h, pivot := cardrank.Order(hands)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s %b\n", h[0]+1, hands[h[0]].Description(), hands[h[0]].Best())
		} else {
			var s, b []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(h[j]+1))
				b = append(b, fmt.Sprintf("%b", hands[h[j]].Best()))
			}
			fmt.Printf("Result:   Players %s push with %s %s\n", strings.Join(s, ", "), hands[h[0]].Description(), strings.Join(b, ", "))
		}
	}
}
Output:

Example (ShortDeck)
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"

	"cardrank.io/cardrank"
)

func main() {
	for i, game := range []struct {
		seed    int64
		players int
	}{
		{119, 2},
		{155, 4},
		{384, 8},
		{880, 4},
		{3453, 3},
		{5662, 3},
		{65481, 2},
		{27947, 4},
	} {
		// note: use a real random source
		rnd := rand.New(rand.NewSource(game.seed))
		pockets, board := cardrank.ShortDeck.Deal(rnd.Shuffle, game.players)
		hands := cardrank.ShortDeck.RankHands(pockets, board)
		fmt.Printf("------ ShortDeck %d ------\n", i+1)
		fmt.Printf("Board:    %b\n", board)
		for j := 0; j < game.players; j++ {
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, hands[j].Pocket(), hands[j].Description(), hands[j].Best(), hands[j].Unused())
		}
		h, pivot := cardrank.Order(hands)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s %b\n", h[0]+1, hands[h[0]].Description(), hands[h[0]].Best())
		} else {
			var s, b []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(h[j]+1))
				b = append(b, fmt.Sprintf("%b", hands[h[j]].Best()))
			}
			fmt.Printf("Result:   Players %s push with %s %s\n", strings.Join(s, ", "), hands[h[0]].Description(), strings.Join(b, ", "))
		}
	}
}
Output:

------ ShortDeck 1 ------
Board:    [9♥ A♦ A♥ 8♣ A♣]
Player 1: [8♥ 7♥] Full House, Aces full of Eights [A♣ A♦ A♥ 8♣ 8♥] [9♥ 7♥]
Player 2: [A♠ J♦] Four of a Kind, Aces, kicker Jack [A♣ A♦ A♥ A♠ J♦] [9♥ 8♣]
Result:   Player 2 wins with Four of a Kind, Aces, kicker Jack [A♣ A♦ A♥ A♠ J♦]
------ ShortDeck 2 ------
Board:    [9♣ 6♦ A♠ J♠ 6♠]
Player 1: [T♥ 6♣] Three of a Kind, Sixes, kickers Ace, Jack [6♣ 6♦ 6♠ A♠ J♠] [T♥ 9♣]
Player 2: [6♥ 9♥] Full House, Sixes full of Nines [6♦ 6♥ 6♠ 9♣ 9♥] [A♠ J♠]
Player 3: [A♣ 7♣] Two Pair, Aces over Sixes, kicker Jack [A♣ A♠ 6♦ 6♠ J♠] [9♣ 7♣]
Player 4: [T♠ K♠] Flush, Ace-high [A♠ K♠ J♠ T♠ 6♠] [9♣ 6♦]
Result:   Player 4 wins with Flush, Ace-high [A♠ K♠ J♠ T♠ 6♠]
------ ShortDeck 3 ------
Board:    [T♥ J♣ 7♥ 9♥ K♣]
Player 1: [8♥ T♠] Straight, Jack-high [J♣ T♥ 9♥ 8♥ 7♥] [K♣ T♠]
Player 2: [J♠ 6♣] Pair, Jacks, kickers King, Ten, Nine [J♣ J♠ K♣ T♥ 9♥] [7♥ 6♣]
Player 3: [7♦ 8♠] Straight, Jack-high [J♣ T♥ 9♥ 8♠ 7♦] [K♣ 7♥]
Player 4: [9♣ A♥] Pair, Nines, kickers Ace, King, Jack [9♣ 9♥ A♥ K♣ J♣] [T♥ 7♥]
Player 5: [T♣ Q♠] Straight, King-high [K♣ Q♠ J♣ T♣ 9♥] [T♥ 7♥]
Player 6: [7♣ Q♦] Straight, King-high [K♣ Q♦ J♣ T♥ 9♥] [7♣ 7♥]
Player 7: [6♠ 8♦] Straight, Jack-high [J♣ T♥ 9♥ 8♦ 7♥] [K♣ 6♠]
Player 8: [K♥ K♦] Three of a Kind, Kings, kickers Jack, Ten [K♣ K♦ K♥ J♣ T♥] [9♥ 7♥]
Result:   Players 5, 6 push with Straight, King-high [K♣ Q♠ J♣ T♣ 9♥], [K♣ Q♦ J♣ T♥ 9♥]
------ ShortDeck 4 ------
Board:    [T♦ 9♣ 9♦ Q♦ 8♦]
Player 1: [J♠ T♥] Straight, Queen-high [Q♦ J♠ T♦ 9♣ 8♦] [T♥ 9♦]
Player 2: [6♣ A♣] Pair, Nines, kickers Ace, Queen, Ten [9♣ 9♦ A♣ Q♦ T♦] [8♦ 6♣]
Player 3: [9♥ 8♠] Full House, Nines full of Eights [9♣ 9♦ 9♥ 8♦ 8♠] [Q♦ T♦]
Player 4: [J♦ A♦] Straight Flush, Queen-high [Q♦ J♦ T♦ 9♦ 8♦] [9♣ A♦]
Result:   Player 4 wins with Straight Flush, Queen-high [Q♦ J♦ T♦ 9♦ 8♦]
------ ShortDeck 5 ------
Board:    [6♠ A♣ 7♦ A♠ 6♦]
Player 1: [9♣ T♠] Two Pair, Aces over Sixes, kicker Ten [A♣ A♠ 6♦ 6♠ T♠] [9♣ 7♦]
Player 2: [J♥ T♦] Two Pair, Aces over Sixes, kicker Jack [A♣ A♠ 6♦ 6♠ J♥] [T♦ 7♦]
Player 3: [K♠ A♥] Full House, Aces full of Sixes [A♣ A♥ A♠ 6♦ 6♠] [K♠ 7♦]
Result:   Player 3 wins with Full House, Aces full of Sixes [A♣ A♥ A♠ 6♦ 6♠]
------ ShortDeck 6 ------
Board:    [A♣ 6♣ 9♣ T♦ 8♣]
Player 1: [6♥ 7♣] Straight Flush, Nine-high, Iron Maiden [9♣ 8♣ 7♣ 6♣ A♣] [T♦ 6♥]
Player 2: [6♠ 9♠] Two Pair, Nines over Sixes, kicker Ace [9♣ 9♠ 6♣ 6♠ A♣] [T♦ 8♣]
Player 3: [J♥ Q♠] Straight, Queen-high [Q♠ J♥ T♦ 9♣ 8♣] [A♣ 6♣]
Result:   Player 1 wins with Straight Flush, Nine-high, Iron Maiden [9♣ 8♣ 7♣ 6♣ A♣]
------ ShortDeck 7 ------
Board:    [K♥ K♦ K♠ K♣ J♣]
Player 1: [7♦ T♦] Four of a Kind, Kings, kicker Jack [K♣ K♦ K♥ K♠ J♣] [T♦ 7♦]
Player 2: [8♦ 6♥] Four of a Kind, Kings, kicker Jack [K♣ K♦ K♥ K♠ J♣] [8♦ 6♥]
Result:   Players 1, 2 push with Four of a Kind, Kings, kicker Jack [K♣ K♦ K♥ K♠ J♣], [K♣ K♦ K♥ K♠ J♣]
------ ShortDeck 8 ------
Board:    [8♦ 8♥ 8♠ Q♠ T♦]
Player 1: [J♦ T♣] Full House, Eights full of Tens [8♦ 8♥ 8♠ T♣ T♦] [Q♠ J♦]
Player 2: [K♠ T♠] Full House, Eights full of Tens [8♦ 8♥ 8♠ T♦ T♠] [K♠ Q♠]
Player 3: [9♣ J♣] Straight, Queen-high [Q♠ J♣ T♦ 9♣ 8♦] [8♥ 8♠]
Player 4: [T♥ 7♥] Full House, Eights full of Tens [8♦ 8♥ 8♠ T♦ T♥] [Q♠ 7♥]
Result:   Players 1, 2, 4 push with Full House, Eights full of Tens [8♦ 8♥ 8♠ T♣ T♦], [8♦ 8♥ 8♠ T♦ T♠], [8♦ 8♥ 8♠ T♦ T♥]
Example (Stud)
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"

	"cardrank.io/cardrank"
)

func main() {
	for i, game := range []struct {
		seed    int64
		players int
	}{
		{119, 2},
		{321, 5},
		{408, 6},
		{455, 6},
		{1113, 6},
	} {
		// note: use a real random source
		rnd := rand.New(rand.NewSource(game.seed))
		pockets, _ := cardrank.Stud.Deal(rnd.Shuffle, game.players)
		hands := cardrank.Stud.RankHands(pockets, nil)
		fmt.Printf("------ Stud %d ------\n", i+1)
		for j := 0; j < game.players; j++ {
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, hands[j].Pocket(), hands[j].Description(), hands[j].Best(), hands[j].Unused())
		}
		h, pivot := cardrank.Order(hands)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s %b\n", h[0]+1, hands[h[0]].Description(), hands[h[0]].Best())
		} else {
			var s, b []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(h[j]+1))
				b = append(b, fmt.Sprintf("%b", hands[h[j]].Best()))
			}
			fmt.Printf("Result:   Players %s push with %s %s\n", strings.Join(s, ", "), hands[h[0]].Description(), strings.Join(b, ", "))
		}
	}
}
Output:

------ Stud 1 ------
Player 1: [K♥ 7♣ J♣ 4♣ A♥ 5♠ Q♠] Nothing, Ace-high, kickers King, Queen, Jack, Seven [A♥ K♥ Q♠ J♣ 7♣] [5♠ 4♣]
Player 2: [2♠ 6♣ 3♥ 5♥ 4♥ Q♦ 7♥] Straight, Seven-high [7♥ 6♣ 5♥ 4♥ 3♥] [Q♦ 2♠]
Result:   Player 2 wins with Straight, Seven-high [7♥ 6♣ 5♥ 4♥ 3♥]
------ Stud 2 ------
Player 1: [3♠ 6♦ Q♦ K♦ J♦ 3♦ Q♣] Flush, King-high [K♦ Q♦ J♦ 6♦ 3♦] [Q♣ 3♠]
Player 2: [K♠ T♦ 2♥ T♠ 8♥ 8♣ 8♦] Full House, Eights full of Tens [8♣ 8♦ 8♥ T♦ T♠] [K♠ 2♥]
Player 3: [Q♥ Q♠ 6♣ A♥ 4♥ 6♠ T♥] Two Pair, Queens over Sixes, kicker Ace [Q♥ Q♠ 6♣ 6♠ A♥] [T♥ 4♥]
Player 4: [3♥ 7♣ 3♣ 5♦ 9♠ T♣ 9♣] Two Pair, Nines over Threes, kicker Ten [9♣ 9♠ 3♣ 3♥ T♣] [7♣ 5♦]
Player 5: [J♠ 7♠ K♥ 7♥ 2♣ 2♦ A♦] Two Pair, Sevens over Twos, kicker Ace [7♥ 7♠ 2♣ 2♦ A♦] [K♥ J♠]
Result:   Player 2 wins with Full House, Eights full of Tens [8♣ 8♦ 8♥ T♦ T♠]
------ Stud 3 ------
Player 1: [K♠ J♠ 3♠ 5♣ 7♠ 4♠ Q♠] Flush, King-high [K♠ Q♠ J♠ 7♠ 4♠] [3♠ 5♣]
Player 2: [3♣ T♠ 5♥ 3♥ 8♦ 4♣ 8♥] Two Pair, Eights over Threes, kicker Ten [8♦ 8♥ 3♣ 3♥ T♠] [5♥ 4♣]
Player 3: [2♣ T♦ 6♠ K♦ J♦ 2♠ Q♦] Pair, Twos, kickers King, Queen, Jack [2♣ 2♠ K♦ Q♦ J♦] [T♦ 6♠]
Player 4: [2♦ A♣ T♣ 7♥ J♣ T♥ 4♥] Pair, Tens, kickers Ace, Jack, Seven [T♣ T♥ A♣ J♣ 7♥] [4♥ 2♦]
Player 5: [8♠ K♣ 7♣ Q♣ K♥ 9♦ 6♦] Pair, Kings, kickers Queen, Nine, Eight [K♣ K♥ Q♣ 9♦ 8♠] [7♣ 6♦]
Player 6: [5♠ J♥ 7♦ 3♦ 2♥ A♦ 9♣] Nothing, Ace-high, kickers Jack, Nine, Seven, Five [A♦ J♥ 9♣ 7♦ 5♠] [3♦ 2♥]
Result:   Player 1 wins with Flush, King-high [K♠ Q♠ J♠ 7♠ 4♠]
------ Stud 4 ------
Player 1: [6♠ Q♥ 2♣ 9♠ 3♦ T♣ K♥] Nothing, King-high, kickers Queen, Ten, Nine, Six [K♥ Q♥ T♣ 9♠ 6♠] [3♦ 2♣]
Player 2: [4♥ 6♥ J♥ 4♦ Q♦ A♣ J♣] Two Pair, Jacks over Fours, kicker Ace [J♣ J♥ 4♦ 4♥ A♣] [Q♦ 6♥]
Player 3: [5♣ K♠ K♣ A♠ 8♣ 5♥ Q♠] Two Pair, Kings over Fives, kicker Ace [K♣ K♠ 5♣ 5♥ A♠] [Q♠ 8♣]
Player 4: [J♠ 8♦ 7♥ 2♠ 2♦ 6♦ 6♣] Two Pair, Sixes over Twos, kicker Jack [6♣ 6♦ 2♦ 2♠ J♠] [8♦ 7♥]
Player 5: [8♥ Q♣ 5♦ 7♣ 9♥ K♦ 9♣] Pair, Nines, kickers King, Queen, Eight [9♣ 9♥ K♦ Q♣ 8♥] [7♣ 5♦]
Player 6: [7♦ A♥ 3♠ 3♣ T♠ T♥ 2♥] Two Pair, Tens over Threes, kicker Ace [T♥ T♠ 3♣ 3♠ A♥] [7♦ 2♥]
Result:   Player 3 wins with Two Pair, Kings over Fives, kicker Ace [K♣ K♠ 5♣ 5♥ A♠]
------ Stud 5 ------
Player 1: [3♦ T♥ A♣ 7♦ 5♣ 6♠ 4♦] Straight, Seven-high [7♦ 6♠ 5♣ 4♦ 3♦] [A♣ T♥]
Player 2: [J♠ 9♠ 3♣ Q♠ 7♠ 5♦ K♠] Flush, King-high [K♠ Q♠ J♠ 9♠ 7♠] [5♦ 3♣]
Player 3: [T♠ 8♠ J♥ 7♥ J♣ 2♣ 3♠] Pair, Jacks, kickers Ten, Eight, Seven [J♣ J♥ T♠ 8♠ 7♥] [3♠ 2♣]
Player 4: [7♣ 2♠ 2♥ 4♥ 4♣ K♣ 6♦] Two Pair, Fours over Twos, kicker King [4♣ 4♥ 2♥ 2♠ K♣] [7♣ 6♦]
Player 5: [A♠ 9♦ K♥ 5♠ 8♦ 6♥ 8♥] Pair, Eights, kickers Ace, King, Nine [8♦ 8♥ A♠ K♥ 9♦] [6♥ 5♠]
Player 6: [K♦ 8♣ 2♦ A♥ 6♣ 4♠ T♦] Nothing, Ace-high, kickers King, Ten, Eight, Six [A♥ K♦ T♦ 8♣ 6♣] [4♠ 2♦]
Result:   Player 2 wins with Flush, King-high [K♠ Q♠ J♠ 9♠ 7♠]
Example (StudHiLo)
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"

	"cardrank.io/cardrank"
)

func main() {
	for i, game := range []struct {
		seed    int64
		players int
	}{
		{119, 2},
		{321, 5},
		{408, 6},
		{455, 6},
		{1113, 6},
	} {
		// note: use a real random source
		rnd := rand.New(rand.NewSource(game.seed))
		pockets, _ := cardrank.StudHiLo.Deal(rnd.Shuffle, game.players)
		hands := cardrank.StudHiLo.RankHands(pockets, nil)
		fmt.Printf("------ StudHiLo %d ------\n", i+1)
		for j := 0; j < game.players; j++ {
			fmt.Printf("Player %d: %b\n", j+1, pockets[j])
			fmt.Printf("  Hi: %s %b %b\n", hands[j].Description(), hands[j].Best(), hands[j].Unused())
			if hands[j].LowValid() {
				fmt.Printf("  Lo: %s %b %b\n", hands[j].LowDescription(), hands[j].LowBest(), hands[j].LowUnused())
			} else {
				fmt.Printf("  Lo: None\n")
			}
		}
		h, hPivot := cardrank.Order(hands)
		l, lPivot := cardrank.LowOrder(hands)
		typ := "wins"
		if lPivot == 0 {
			typ = "scoops"
		}
		if hPivot == 1 {
			fmt.Printf("Result (Hi): Player %d %s with %s %b\n", h[0]+1, typ, hands[h[0]].Description(), hands[h[0]].Best())
		} else {
			var s, b []string
			for j := 0; j < hPivot; j++ {
				s = append(s, strconv.Itoa(h[j]+1))
				b = append(b, fmt.Sprintf("%b", hands[h[j]].Best()))
			}
			fmt.Printf("Result (Hi): Players %s push with %s %s\n", strings.Join(s, ", "), hands[h[0]].Description(), strings.Join(b, ", "))
		}
		if lPivot == 1 {
			fmt.Printf("Result (Lo): Player %d wins with %s %b\n", l[0]+1, hands[l[0]].LowDescription(), hands[l[0]].LowBest())
		} else if lPivot > 1 {
			var s, b []string
			for j := 0; j < lPivot; j++ {
				s = append(s, strconv.Itoa(l[j]+1))
				b = append(b, fmt.Sprintf("%b", hands[l[j]].LowBest()))
			}
			fmt.Printf("Result (Lo): Players %s push with %s %s\n", strings.Join(s, ", "), hands[l[0]].LowDescription(), strings.Join(b, ", "))
		} else {
			fmt.Printf("Result (Lo): no player made a low hand\n")
		}
	}
}
Output:

------ StudHiLo 1 ------
Player 1: [K♥ 7♣ J♣ 4♣ A♥ 5♠ Q♠]
  Hi: Nothing, Ace-high, kickers King, Queen, Jack, Seven [A♥ K♥ Q♠ J♣ 7♣] [5♠ 4♣]
  Lo: None
Player 2: [2♠ 6♣ 3♥ 5♥ 4♥ Q♦ 7♥]
  Hi: Straight, Seven-high [7♥ 6♣ 5♥ 4♥ 3♥] [Q♦ 2♠]
  Lo: Six-low [6♣ 5♥ 4♥ 3♥ 2♠] [Q♦ 7♥]
Result (Hi): Player 2 wins with Straight, Seven-high [7♥ 6♣ 5♥ 4♥ 3♥]
Result (Lo): Player 2 wins with Six-low [6♣ 5♥ 4♥ 3♥ 2♠]
------ StudHiLo 2 ------
Player 1: [3♠ 6♦ Q♦ K♦ J♦ 3♦ Q♣]
  Hi: Flush, King-high [K♦ Q♦ J♦ 6♦ 3♦] [Q♣ 3♠]
  Lo: None
Player 2: [K♠ T♦ 2♥ T♠ 8♥ 8♣ 8♦]
  Hi: Full House, Eights full of Tens [8♣ 8♦ 8♥ T♦ T♠] [K♠ 2♥]
  Lo: None
Player 3: [Q♥ Q♠ 6♣ A♥ 4♥ 6♠ T♥]
  Hi: Two Pair, Queens over Sixes, kicker Ace [Q♥ Q♠ 6♣ 6♠ A♥] [T♥ 4♥]
  Lo: None
Player 4: [3♥ 7♣ 3♣ 5♦ 9♠ T♣ 9♣]
  Hi: Two Pair, Nines over Threes, kicker Ten [9♣ 9♠ 3♣ 3♥ T♣] [7♣ 5♦]
  Lo: None
Player 5: [J♠ 7♠ K♥ 7♥ 2♣ 2♦ A♦]
  Hi: Two Pair, Sevens over Twos, kicker Ace [7♥ 7♠ 2♣ 2♦ A♦] [K♥ J♠]
  Lo: None
Result (Hi): Player 2 scoops with Full House, Eights full of Tens [8♣ 8♦ 8♥ T♦ T♠]
Result (Lo): no player made a low hand
------ StudHiLo 3 ------
Player 1: [K♠ J♠ 3♠ 5♣ 7♠ 4♠ Q♠]
  Hi: Flush, King-high [K♠ Q♠ J♠ 7♠ 4♠] [3♠ 5♣]
  Lo: None
Player 2: [3♣ T♠ 5♥ 3♥ 8♦ 4♣ 8♥]
  Hi: Two Pair, Eights over Threes, kicker Ten [8♦ 8♥ 3♣ 3♥ T♠] [5♥ 4♣]
  Lo: None
Player 3: [2♣ T♦ 6♠ K♦ J♦ 2♠ Q♦]
  Hi: Pair, Twos, kickers King, Queen, Jack [2♣ 2♠ K♦ Q♦ J♦] [T♦ 6♠]
  Lo: None
Player 4: [2♦ A♣ T♣ 7♥ J♣ T♥ 4♥]
  Hi: Pair, Tens, kickers Ace, Jack, Seven [T♣ T♥ A♣ J♣ 7♥] [4♥ 2♦]
  Lo: None
Player 5: [8♠ K♣ 7♣ Q♣ K♥ 9♦ 6♦]
  Hi: Pair, Kings, kickers Queen, Nine, Eight [K♣ K♥ Q♣ 9♦ 8♠] [7♣ 6♦]
  Lo: None
Player 6: [5♠ J♥ 7♦ 3♦ 2♥ A♦ 9♣]
  Hi: Nothing, Ace-high, kickers Jack, Nine, Seven, Five [A♦ J♥ 9♣ 7♦ 5♠] [3♦ 2♥]
  Lo: Seven-low [7♦ 5♠ 3♦ 2♥ A♦] [J♥ 9♣]
Result (Hi): Player 1 wins with Flush, King-high [K♠ Q♠ J♠ 7♠ 4♠]
Result (Lo): Player 6 wins with Seven-low [7♦ 5♠ 3♦ 2♥ A♦]
------ StudHiLo 4 ------
Player 1: [6♠ Q♥ 2♣ 9♠ 3♦ T♣ K♥]
  Hi: Nothing, King-high, kickers Queen, Ten, Nine, Six [K♥ Q♥ T♣ 9♠ 6♠] [3♦ 2♣]
  Lo: None
Player 2: [4♥ 6♥ J♥ 4♦ Q♦ A♣ J♣]
  Hi: Two Pair, Jacks over Fours, kicker Ace [J♣ J♥ 4♦ 4♥ A♣] [Q♦ 6♥]
  Lo: None
Player 3: [5♣ K♠ K♣ A♠ 8♣ 5♥ Q♠]
  Hi: Two Pair, Kings over Fives, kicker Ace [K♣ K♠ 5♣ 5♥ A♠] [Q♠ 8♣]
  Lo: None
Player 4: [J♠ 8♦ 7♥ 2♠ 2♦ 6♦ 6♣]
  Hi: Two Pair, Sixes over Twos, kicker Jack [6♣ 6♦ 2♦ 2♠ J♠] [8♦ 7♥]
  Lo: None
Player 5: [8♥ Q♣ 5♦ 7♣ 9♥ K♦ 9♣]
  Hi: Pair, Nines, kickers King, Queen, Eight [9♣ 9♥ K♦ Q♣ 8♥] [7♣ 5♦]
  Lo: None
Player 6: [7♦ A♥ 3♠ 3♣ T♠ T♥ 2♥]
  Hi: Two Pair, Tens over Threes, kicker Ace [T♥ T♠ 3♣ 3♠ A♥] [7♦ 2♥]
  Lo: None
Result (Hi): Player 3 scoops with Two Pair, Kings over Fives, kicker Ace [K♣ K♠ 5♣ 5♥ A♠]
Result (Lo): no player made a low hand
------ StudHiLo 5 ------
Player 1: [3♦ T♥ A♣ 7♦ 5♣ 6♠ 4♦]
  Hi: Straight, Seven-high [7♦ 6♠ 5♣ 4♦ 3♦] [A♣ T♥]
  Lo: Six-low [6♠ 5♣ 4♦ 3♦ A♣] [T♥ 7♦]
Player 2: [J♠ 9♠ 3♣ Q♠ 7♠ 5♦ K♠]
  Hi: Flush, King-high [K♠ Q♠ J♠ 9♠ 7♠] [5♦ 3♣]
  Lo: None
Player 3: [T♠ 8♠ J♥ 7♥ J♣ 2♣ 3♠]
  Hi: Pair, Jacks, kickers Ten, Eight, Seven [J♣ J♥ T♠ 8♠ 7♥] [3♠ 2♣]
  Lo: None
Player 4: [7♣ 2♠ 2♥ 4♥ 4♣ K♣ 6♦]
  Hi: Two Pair, Fours over Twos, kicker King [4♣ 4♥ 2♥ 2♠ K♣] [7♣ 6♦]
  Lo: None
Player 5: [A♠ 9♦ K♥ 5♠ 8♦ 6♥ 8♥]
  Hi: Pair, Eights, kickers Ace, King, Nine [8♦ 8♥ A♠ K♥ 9♦] [6♥ 5♠]
  Lo: None
Player 6: [K♦ 8♣ 2♦ A♥ 6♣ 4♠ T♦]
  Hi: Nothing, Ace-high, kickers King, Ten, Eight, Six [A♥ K♦ T♦ 8♣ 6♣] [4♠ 2♦]
  Lo: Eight-low [8♣ 6♣ 4♠ 2♦ A♥] [K♦ T♦]
Result (Hi): Player 2 wins with Flush, King-high [K♠ Q♠ J♠ 9♠ 7♠]
Result (Lo): Player 1 wins with Six-low [6♠ 5♣ 4♦ 3♦ A♣]

Index

Examples

Constants

View Source
const (
	UnicodeSpadeAce     rune = '🂡'
	UnicodeHeartAce     rune = '🂱'
	UnicodeDiamondAce   rune = '🃁'
	UnicodeClubAce      rune = '🃑'
	UnicodeSpadeBlack   rune = '♠'
	UnicodeSpadeWhite   rune = '♤'
	UnicodeHeartBlack   rune = '♥'
	UnicodeHeartWhite   rune = '♡'
	UnicodeDiamondBlack rune = '♦'
	UnicodeDiamondWhite rune = '♢'
	UnicodeClubBlack    rune = '♣'
	UnicodeClubWhite    rune = '♧'
)

Unicode card runes.

View Source
const (
	// UnshuffledSize is the unshuffled deck size.
	UnshuffledSize = 52
	// UnshuffledShortSize is the unshuffled short deck size.
	UnshuffledShortSize = 36
)
View Source
const EightOrBetterMaxRank = 512

EightOrBetterMaxRank is the eight-or-better max rank.

View Source
const LowMaxRank = 16384

LowMaxRank is the low max rank.

Variables

This section is empty.

Functions

func CactusFastRanker added in v0.1.3

func CactusFastRanker(c0, c1, c2, c3, c4 Card) uint16

CactusFastRanker is a cactus fast hand ranker.

func CactusRanker added in v0.1.3

func CactusRanker(c0, c1, c2, c3, c4 Card) uint16

CactusRanker is a cactus-kev hand ranker.

func EightOrBetterRanker added in v0.1.3

func EightOrBetterRanker(c0, c1, c2, c3, c4 Card) uint16

EightOrBetterRanker is a eight-or-better low hand ranker.

func LowOrder added in v0.1.3

func LowOrder(hands []*Hand) ([]int, int)

LowOrder orders hands by rank, low to high, returning 'pivot' of winning vs losing hands. If there are no low hands the pivot will be 0.

func LowRanker added in v0.1.3

func LowRanker(c0, c1, c2, c3, c4 Card) uint16

LowRanker is a low hand ranker.

func Order added in v0.1.3

func Order(hands []*Hand) ([]int, int)

Order orders hands by rank, low to high, returning 'pivot' of winning vs losing hands. Pivot will always be 1 or higher.

func PlayingCardKnightRune

func PlayingCardKnightRune(r Rank, s Suit) rune

PlayingCardKnightRune returns the unicode playing card rune for the card rank and suit, substituting knights for jacks.

func PlayingCardRune

func PlayingCardRune(r Rank, s Suit) rune

PlayingCardRune returns the unicode playing card rune for the card rank and suit.

Types

type Card

type Card uint32

Card is a card consisting of a rank (23456789TJQKA) and suit (shdc).

Example (Unmarshal)
package main

import (
	"encoding/json"
	"fmt"
	"log"

	"cardrank.io/cardrank"
)

func main() {
	var hand []cardrank.Card
	if err := json.Unmarshal([]byte(`["3s", "4c", "5c", "Ah", "2d"]`), &hand); err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", hand)
}
Output:

[3s 4c 5c Ah 2d]

func FromRune

func FromRune(r rune) (Card, error)

FromRune creates a card from a unicode playing card rune.

Example
package main

import (
	"fmt"
	"log"

	"cardrank.io/cardrank"
)

func main() {
	c, err := cardrank.FromRune('🂡')
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%b\n", c)
}
Output:

A♠

func FromString

func FromString(str string) (Card, error)

FromString creates a card from a string.

func Must

func Must(v ...string) []Card

Must creates a hand from v.

func MustCard

func MustCard(s string) Card

MustCard creates card from s.

Example
package main

import (
	"fmt"

	"cardrank.io/cardrank"
)

func main() {
	c := cardrank.MustCard("Ah")
	fmt.Printf("%N of %L (%b)\n", c, c, c)
}
Output:

Ace of Hearts (A♥)

func New

func New(r Rank, s Suit) Card

New creates a card for the specified rank and suit.

func Parse

func Parse(v ...string) ([]Card, error)

Parse parses card representations in v.

func Unshuffled

func Unshuffled() []Card

Unshuffled generates an unshuffled set of standard playing cards.

func UnshuffledExclude

func UnshuffledExclude(exclude []Card) []Card

UnshuffledExclude generates an unshuffled set of cards, with excluded cards removed.

func UnshuffledShortDeck

func UnshuffledShortDeck() []Card

UnshuffledShortDeck generates an unshuffled set of short deck cards (ie, excluding card ranks 2 through 5).

func (Card) BitRank

func (c Card) BitRank() uint32

BitRank returns the bit rank of the card.

func (Card) Format

func (c Card) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

Supported verbs:

s - rank (23456789TJQKA) and suit (shdc) (ex: Ks Ah)
S - same as s, uppercased (ex: KS AH)
q - same as s, quoted (ex: "Ks" "Ah")
v - same as s
r - rank (as in s) without suit (ex: K A)
u - suit (as in s) without rank (shdc)
b - rank (as in s) and the black unicode pip rune (♠♥♦♣) (ex: K♠ A♥)
B - black unicode pip rune (as in b) without rank (♠♥♦♣)
h - rank (as in s) and the white unicode pip rune (♤♡♢♧) (ex: K♤ A♡)
H - white unicode pip rune (as in h) without rank (♤♡♢♧)
c - playing card rune (ex: 🂡  🂱  🃁  🃑)
C - playing card rune (as in c), substituting knights for jacks (ex: 🂬  🂼  🃌  🃜)
n - rank name, lower cased (ex: one two jack queen king ace)
N - rank name, title cased (ex: One Two Jack Queen King Ace)
p - plural rank name, lower cased (ex: ones twos sixes)
P - plural rank name, title cased (ex: Ones Twos Sixes)
t - suit name, lower cased (spade heart diamond club)
T - suit name, title cased (Spade Heart Diamond Club)
l - plural suit name, lower cased (spades hearts diamonds clubs)
L - plural suit name, title cased (Spades Hearts Diamonds Clubs)
d - base 10 integer value

func (Card) MarshalText

func (c Card) MarshalText() ([]byte, error)

MarshalText satisfies the encoding.TextMarshaler interface.

func (Card) Prime

func (c Card) Prime() uint32

Prime returns the prime value of the card.

func (Card) Rank

func (c Card) Rank() Rank

Rank returns the rank of the card.

func (Card) RankByte

func (c Card) RankByte() byte

RankByte returns the rank byte of the card.

func (Card) RankIndex

func (c Card) RankIndex() int

RankIndex returns the rank index of the card.

func (Card) String

func (c Card) String() string

String satisfies the fmt.Stringer interface.

func (Card) Suit

func (c Card) Suit() Suit

Suit returns the suit of the card.

func (Card) SuitByte

func (c Card) SuitByte() byte

SuitByte returns the suit byte of the card.

func (Card) SuitIndex

func (c Card) SuitIndex() int

SuitIndex returns the suit index of the card.

func (*Card) UnmarshalText

func (c *Card) UnmarshalText(buf []byte) error

UnmarshalText satisfies the encoding.TextUnmarshaler interface.

type Deck

type Deck struct {
	// contains filtered or unexported fields
}

Deck is a set of playing cards.

func NewDeck

func NewDeck(cards ...Card) *Deck

NewDeck creates a new deck of cards. If no cards are provided, then a deck will be created using the standard unshuffled cards.

func NewDeckShoe

func NewDeckShoe(n int) *Deck

NewDeckShoe creates a card deck "shoe" composed of n decks of unshuffled cards.

func NewShortDeck

func NewShortDeck() *Deck

NewShortDeck creates a new deck of short cards.

func (*Deck) Badugi added in v0.1.3

func (d *Deck) Badugi(hands int) ([][]Card, []Card)

Badugi draws hands for Badugi, returning the sets of pockets (one per hand). Deals no board cards.

func (*Deck) Board

func (d *Deck) Board(counts ...int) []Card

Board draws board cards by discarding a card and drawing n cards for each n in counts.

func (*Deck) Deal

func (d *Deck) Deal(hands, n int) [][]Card

Deal draws one card successively for each hand until each hand has n cards.

func (*Deck) Draw

func (d *Deck) Draw(n int) []Card

Draw draws the next n cards from the top (front) of the deck.

Example
package main

import (
	"fmt"
	"math/rand"

	"cardrank.io/cardrank"
)

func main() {
	d := cardrank.NewDeck()
	// note: use a real random source
	rnd := rand.New(rand.NewSource(52))
	d.Shuffle(rnd.Shuffle)
	hand := d.Draw(7)
	fmt.Printf("%b\n", hand)
}
Output:

[9♣ 6♥ Q♠ 3♠ J♠ 9♥ K♣]

func (*Deck) Empty

func (d *Deck) Empty() bool

Empty returns true when there are no cards remaining in the deck.

func (*Deck) Holdem

func (d *Deck) Holdem(hands int) ([][]Card, []Card)

Holdem draws hands for Texas Holdem, returning the set of pockets (one per hand) and board cards. Deals 1 card per player until each player has 2 pocket cards, then discards a card, deals 3 board cards, discards another, deals another board card, discards another, and deals a final card to the board.

func (*Deck) HoldemSimple

func (d *Deck) HoldemSimple(hands int) ([][]Card, []Card)

HoldemSimple draws hands for Texas Holdem, returning the set of pockets (one per hand) and board cards. Useful for examples. Deals 5 board cards prior to dealing pocket cards for each hand.

func (*Deck) Omaha

func (d *Deck) Omaha(hands int) ([][]Card, []Card)

Omaha draws hands for Omaha, returning the set of pockets (one per hand) and board cards.

func (*Deck) OmahaSimple

func (d *Deck) OmahaSimple(hands int) ([][]Card, []Card)

OmahaSimple draws hands for Omaha, returning the set of pockets (one per hand) and board cards. Useful for examples. Deals 5 board cards prior to dealing pocket cards for each hand.

func (*Deck) Remaining

func (d *Deck) Remaining() int

Remaining returns the number of remaining cards in the deck.

func (*Deck) SetLimit

func (d *Deck) SetLimit(limit int)

SetLimit sets a limit for the deck.

Useful when using a card deck "shoe" composed of more than one deck of cards.

func (*Deck) Shuffle

func (d *Deck) Shuffle(f func(int, func(i, j int)))

Shuffle shuffles the deck's cards using f (same interface as math/rand.Shuffle).

func (*Deck) ShuffleN

func (d *Deck) ShuffleN(f func(n int, swap func(i, j int)), n int)

ShuffleN shuffles the deck's cards, n times, using f (same interface as math/rand.Shuffle).

func (*Deck) Simple

func (d *Deck) Simple(board, hands, n int) ([][]Card, []Card)

Simple draws board cards and hands of n cards. Useful for examples.

func (*Deck) Stud added in v0.1.3

func (d *Deck) Stud(hands int) ([][]Card, []Card)

Stud draws hands for Stud, returning the sets of pockets (one per hand). Deals no board cards.

type Error

type Error string

Error is a error.

const (
	// ErrInvalidCard is the invalid card error.
	ErrInvalidCard Error = "invalid card"
	// ErrInvalidCardRank is the invalid card rank error.
	ErrInvalidCardRank Error = "invalid card rank"
	// ErrInvalidCardSuit is the invalid card suit error.
	ErrInvalidCardSuit Error = "invalid card suit"
)

Error values.

func (Error) Error

func (err Error) Error() string

Error satisfies the error interface.

type Hand

type Hand struct {
	// contains filtered or unexported fields
}

Hand is a poker hand.

func NewHand

func NewHand(typ Type, pocket, board []Card) *Hand

NewHand creates a new hand of the specified type.

Example
package main

import (
	"fmt"
	"math/rand"

	"cardrank.io/cardrank"
)

func main() {
	d := cardrank.NewDeck()
	// note: use a real random source
	rnd := rand.New(rand.NewSource(6265))
	d.Shuffle(rnd.Shuffle)
	hand := d.Draw(5)
	h := cardrank.NewHand(cardrank.Holdem, hand, nil)
	fmt.Printf("%b\n", h)
}
Output:

Four of a Kind, Eights, kicker Seven [8♣ 8♦ 8♥ 8♠ 7♠]

func (*Hand) Best

func (h *Hand) Best() []Card

Best returns the hand's best-five cards.

func (*Hand) Board

func (h *Hand) Board() []Card

Board returns the hand's board.

func (*Hand) Compare

func (h *Hand) Compare(b *Hand) int

Compare compares the hand ranks.

func (*Hand) Description

func (h *Hand) Description() string

Description describes the hand's best-five cards.

Examples:

Straight Flush, Ace-high, Royal
Straight Flush, King-high
Straight Flush, Five-high, Steel Wheel
Four of a Kind, Nines, kicker Jack
Full House, Sixes full of Fours
Flush, Ten-high
Straight, Eight-high
Three of a Kind, Fours, kickers Ace, King
Two Pair, Nines over Sixes, kicker Jack
Pair, Aces, kickers King, Queen, Nine
Nothing, Seven-high, kickers Six, Five, Three, Two

func (*Hand) Fixed

func (h *Hand) Fixed() HandRank

Fixed returns the hand's fixed rank.

func (*Hand) Format

func (h *Hand) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

func (Hand) LowBest added in v0.1.1

func (h Hand) LowBest() []Card

LowBest returns the hand's best-five low cards.

func (*Hand) LowCompare added in v0.1.3

func (h *Hand) LowCompare(b *Hand) int

LowCompare compares the low hand ranks.

func (*Hand) LowDescription added in v0.1.1

func (h *Hand) LowDescription() string

LowDescription describes the hands best-five low cards.

func (Hand) LowRank added in v0.1.3

func (h Hand) LowRank() HandRank

LowRank returns the hand's low rank.

func (Hand) LowUnused added in v0.1.1

func (h Hand) LowUnused() []Card

LowUnused returns the poker hand's unused-five low cards.

func (*Hand) LowValid added in v0.1.3

func (h *Hand) LowValid() bool

LowValid returns true if is a valid low hand.

func (*Hand) Pocket

func (h *Hand) Pocket() []Card

Pocket returns the hand's pocket.

func (*Hand) Rank

func (h *Hand) Rank() HandRank

Rank returns the hand's rank.

func (*Hand) Unused

func (h *Hand) Unused() []Card

Unused returns the hand's unused cards.

type HandFormatter

type HandFormatter []Card

HandFormatter wraps formatting a set of cards. Allows `go test` to function without disabling vet.

func (HandFormatter) Format

func (hand HandFormatter) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

type HandRank

type HandRank uint16

HandRank is a poker hand rank.

const (
	StraightFlush HandRank = 10
	FourOfAKind   HandRank = 166
	FullHouse     HandRank = 322
	Flush         HandRank = 1599
	Straight      HandRank = 1609
	ThreeOfAKind  HandRank = 2467
	TwoPair       HandRank = 3325
	Pair          HandRank = 6185
	Nothing       HandRank = 7462
	HighCard      HandRank = Nothing
	Invalid                = HandRank(^uint16(0))
)

Poker hand rank values.

func (HandRank) Fixed

func (r HandRank) Fixed() HandRank

Fixed converts a relative poker rank to a fixed hand rank.

func (HandRank) Name

func (r HandRank) Name() string

Name returns the hand rank name.

func (HandRank) String

func (r HandRank) String() string

String satisfies the fmt.Stringer interface.

type Rank

type Rank uint8

Rank is a card rank.

const (
	Ace Rank = 12 - iota
	King
	Queen
	Jack
	Ten
	Nine
	Eight
	Seven
	Six
	Five
	Four
	Three
	Two
)

Card ranks.

func RankFromRune

func RankFromRune(r rune) (Rank, error)

RankFromRune returns the card rank for the rune.

func (Rank) Byte

func (r Rank) Byte() byte

Byte returns the byte representation for the card rank.

func (Rank) Index

func (r Rank) Index() int

Index the int index for the card rank (0-13 for Two-Ace).

func (Rank) Name

func (r Rank) Name() string

Name returns the name of the card rank.

func (Rank) PluralName

func (r Rank) PluralName() string

PluralName returns the plural name of the card rank.

func (Rank) String

func (r Rank) String() string

String satisfies the fmt.Stringer interface.

type RankFiveFunc added in v0.1.3

type RankFiveFunc func(c0, c1, c2, c3, c4 Card) uint16

RankFiveFunc ranks a hand of 5 cards.

func SixPlusRanker added in v0.1.3

func SixPlusRanker(f RankFiveFunc) RankFiveFunc

SixPlusRanker creates a short deck (6-plus) hand ranker.

type RankerFunc

type RankerFunc func([]Card) HandRank

RankerFunc ranks a hand of 5, 6, or 7 cards.

var DefaultRanker RankerFunc

DefaultRanker is the default hand ranker.

var DefaultSixPlusRanker RankerFunc

DefaultSixPlusRanker is the default 6-plus (short deck) hand ranker.

func HandRanker added in v0.1.3

func HandRanker(f RankFiveFunc) RankerFunc

HandRanker creates a new hand ranker for 5, 6, or 7 cards that brute forces ranks for 6 and 7 using f.

func HybridRanker added in v0.1.3

func HybridRanker(f5 RankFiveFunc, f7 RankerFunc) RankerFunc

HybridRanker creates a hybrid ranker using f5 for hands with 5 and 6 cards, and f7 for hands with 7 cards.

func NewTwoPlusRanker

func NewTwoPlusRanker() RankerFunc

TwoPlusRanker creates a new two plus hand ranker.

type Suit

type Suit uint8

Suit is a card suit.

const (
	Spade Suit = 1 << iota
	Heart
	Diamond
	Club
)

Card suits.

func SuitFromRune

func SuitFromRune(r rune) (Suit, error)

SuitFromRune returns the card suit for the rune.

func (Suit) Byte

func (s Suit) Byte() byte

Byte returns the byte representation for the card suit.

func (Suit) Index

func (s Suit) Index() int

Index returns the int index for the card suit (0-3 for Spade, Heart, Diamond, Club).

func (Suit) Name

func (s Suit) Name() string

Name returns the name of the card suit.

func (Suit) PluralName

func (s Suit) PluralName() string

PluralName returns the plural name of the card suit.

func (Suit) String

func (s Suit) String() string

String satisfies the fmt.Stringer interface.

func (Suit) UnicodeBlack

func (s Suit) UnicodeBlack() rune

UnicodeBlack returns the black unicode pip rune for the card suit.

func (Suit) UnicodeWhite

func (s Suit) UnicodeWhite() rune

UnicodeWhite returns the white unicode pip rune for the card suit.

type TwoPlusRanker

type TwoPlusRanker struct {
	// contains filtered or unexported fields
}

TwoPlusRanker is a two plus hand ranker.

type Type

type Type uint32

Type is a hand type.

const (
	Holdem Type = iota
	ShortDeck
	Omaha
	OmahaHiLo
	Stud
	StudHiLo
	Razz // FIXME: not yet working
	Badugi
)

Hand types.

func (Type) Best

func (typ Type) Best(pocket, board []Card) (HandRank, []Card, []Card, HandRank, []Card, []Card)

Best returns the best hand and rank for the provided pocket, board. Returns the rank of the best available hand, its best cards, and its unused cards.

func (Type) Deal

func (typ Type) Deal(shuffle func(int, func(int, int)), hands int) ([][]Card, []Card)

Deal deals cards for the type.

func (Type) Deck

func (typ Type) Deck() *Deck

NewDeck returns a new deck for the type.

func (Type) MaxPlayers added in v0.1.3

func (typ Type) MaxPlayers() int

MaxPlayers returns the max players for the type.

func (Type) MultiShuffleDeal

func (typ Type) MultiShuffleDeal(shuffle func(int, func(int, int)), count, hands int) ([][]Card, []Card)

MultiShuffleDeal shuffles a deck multiple times and deals cards for the type.

func (Type) RankHand

func (typ Type) RankHand(pocket, board []Card) *Hand

RankHand ranks the hand.

func (Type) RankHands

func (typ Type) RankHands(pockets [][]Card, board []Card) []*Hand

RankHands ranks the hands.

func (Type) String

func (typ Type) String() string

String satisfies the fmt.Stringer interface.

Directories

Path Synopsis
_example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL