cardrank

package module
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Feb 11, 2023 License: MIT Imports: 8 Imported by: 3

README

About

Package github.com/cardrank/cardrank is a library of types, utilities, and interfaces for working with playing cards, card decks, and evaluating poker hand ranks.

Supports Texas Holdem, Texas Holdem Short (6+), Texas Holdem Royal (10+), Omaha, Omaha Hi/Lo, Stud, Stud Hi/Lo, Razz, and Badugi.

Tests Go Report Card Reference Releases

Overview

The github.com/cardrank/cardrank package contains types for cards, card suits, card ranks, card decks, and hands of cards.

A single package level type provides a standard interface for dealing cards for, and evaluating poker hands of the following:

Hand evaluation and ranking of the different poker hand types is accomplished through pure Go implementations of well-known poker rank evaluation algorithms. Poker hands can be compared and ordered to determine the hand's winner(s).

Development of additional poker variants, such as Kansas City Lowball and Candian Stud (Sökö), is planned.

Using

To use within a Go package or module:

go get github.com/cardrank/cardrank

See package level Go documentation.

Quickstart

Complete examples for Texas Holdem, Texas Holdem Short (6+), Texas Holdem Royal (10+), Omaha, Omaha Hi/Lo, Stud, Stud Hi/Lo, Razz, and Badugi are available in the source repository. Other examples are available in the Go package documentation showing use of the package's types, utilities, and interfaces.

Texas Holdem

The following showcases a simple game of Texas Holdem:

package main

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

	"github.com/cardrank/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, 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, ", "))
	}
}

Output:

------ Holdem 1676110749917132920 ------
Board:    [8♦ 9♠ 2♦ 2♣ J♦]
Player 1: [J♣ 4♠] Two Pair, Jacks over Twos, kicker Nine [J♣ J♦ 2♣ 2♦ 9♠] [8♦ 4♠]
Player 2: [3♣ T♣] Pair, Twos, kickers Jack, Ten, Nine [2♣ 2♦ J♦ T♣ 9♠] [8♦ 3♣]
Player 3: [6♦ 5♣] Pair, Twos, kickers Jack, Nine, Eight [2♣ 2♦ J♦ 9♠ 8♦] [6♦ 5♣]
Player 4: [9♣ 4♣] Two Pair, Nines over Twos, kicker Jack [9♣ 9♠ 2♣ 2♦ J♦] [8♦ 4♣]
Player 5: [7♠ 2♥] Three of a Kind, Twos, kickers Jack, Nine [2♣ 2♦ 2♥ J♦ 9♠] [8♦ 7♠]
Player 6: [T♠ 3♠] Pair, Twos, kickers Jack, Ten, Nine [2♣ 2♦ J♦ T♠ 9♠] [8♦ 3♠]
Result:   Player 5 wins with Three of a Kind, Twos, kickers Jack, Nine [2♣ 2♦ 2♥ J♦ 9♠]
Omaha Hi/Lo

The following showcases a simple game of Omaha Hi/Lo, highlighting Hi/Lo winner determination:

package main

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

	"github.com/cardrank/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, 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())
		fmt.Printf("  Lo: %s %b %b\n", hands[i].LowDescription(), hands[i].LowBest(), hands[i].LowUnused())
	}
	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")
	}
}

Output:

------ OmahaHiLo 1676110711435292197 ------
Board: [9♥ 4♦ A♣ 9♦ 2♣]
Player 1: [J♦ Q♠ J♠ 7♦]
  Hi: Two Pair, Jacks over Nines, kicker Ace [J♦ J♠ 9♦ 9♥ A♣] [Q♠ 7♦ 4♦ 2♣]
  Lo: None [] []
Player 2: [K♥ 2♠ T♥ 3♦]
  Hi: Two Pair, Nines over Twos, kicker King [9♦ 9♥ 2♣ 2♠ K♥] [T♥ 3♦ 4♦ A♣]
  Lo: None [] []
Player 3: [2♦ T♦ K♣ 6♥]
  Hi: Two Pair, Nines over Twos, kicker King [9♦ 9♥ 2♣ 2♦ K♣] [T♦ 6♥ 4♦ A♣]
  Lo: None [] []
Player 4: [9♣ 5♥ J♥ 8♦]
  Hi: Three of a Kind, Nines, kickers Ace, Jack [9♣ 9♦ 9♥ A♣ J♥] [5♥ 8♦ 4♦ 2♣]
  Lo: Eight, Five, Four, Two, Ace-low [8♦ 5♥ 4♦ 2♣ A♣] [9♣ J♥ 9♥ 9♦]
Player 5: [8♠ 6♣ 4♣ Q♥]
  Hi: Two Pair, Nines over Fours, kicker Queen [9♦ 9♥ 4♣ 4♦ Q♥] [8♠ 6♣ A♣ 2♣]
  Lo: Eight, Six, Four, Two, Ace-low [8♠ 6♣ 4♦ 2♣ A♣] [4♣ Q♥ 9♥ 9♦]
Player 6: [T♠ 6♠ 5♠ 5♦]
  Hi: Two Pair, Nines over Fives, kicker Ace [9♦ 9♥ 5♦ 5♠ A♣] [T♠ 6♠ 4♦ 2♣]
  Lo: Six, Five, Four, Two, Ace-low [6♠ 5♠ 4♦ 2♣ A♣] [T♠ 5♦ 9♥ 9♦]
Result (Hi): Player 4 wins with Three of a Kind, Nines, kickers Ace, Jack [9♣ 9♦ 9♥ A♣ J♥]
Result (Lo): Player 6 wins with Six, Five, Four, Two, Ace-low [6♠ 5♠ 4♦ 2♣ A♣]
Hand Ranking

Poker Hand's make use of a HandRank to determine the relative rank of a Hand, on a low-to-high basis. Higher poker hands have a lower value HandRank than lower poker hands. For example, a StraightFlush will have a lower HandRank than a FullHouse.

When a Hand is created, a Hi and Lo (if applicable) HandRank is evaluated, and made available via Hand.Rank and Hand.LowRank methods, respectively. The Hi and Lo HandRank's are evaluated by a EvalRankFunc, dependent on the Hand's Type:

Cactus Kev

For regular poker hand types (Holdem, Royal, Omaha, and Stud), poker hand rank is determined by Go implementations of different Cactus Kev evaluators:

See below for more information on the default rank func in use by the package, and for information on using build tags to enable/disable functionality for different target runtime environments.

Default Rank Func

The package-level DefaultRank variable is used for regular poker evaluation. For most scenarios, the Hybrid rank func provides the best possible evaluation performance, and is used by default when no build tags have been specified.

Hybrid

The Hybrid rank func uses either the CactusFast or an instance of the TwoPlusTwo depending on the Hand having 5, 6, or 7 cards.

Two-Plus-Two

The TwoPlusTwo makes use of a large (approximately 130 MiB) lookup table to accomplish extremely fast 5, 6 and 7 card hand rank evaluation. Due to the large size of the lookup table, the TwoPlusTwo will be excluded when using the using the portable or embedded build tags.

The TwoPlusTwo is disabled by default for GOOS=js (ie, WASM) builds, but can be enabled using the forcefat build tag.

Winner Determination

Winner(s) are determined by the lowest possible HandRank when comparing a Hand's Rank or LowRank against another hand. Two or more hands having a HandRank of equal value indicate that the hands have equivalent HandRank, and thus have both won.

As such, when hands are sorted (low-to-high) by Rank or LowRank, the winner(s) of a hand will be all the hands in the lowest position and having the same HandRank.

Comparing Hands

A Hand can be compared to another Hand using Compare and LowCompare.

Compare and LowCompare return -1, 0, or +1, making it easy to compare or sort hands:

// Compare hands:
if hand1.Compare(hand2) < 0 {
	fmt.Printf("%s is a winner!", hand1)
}

// Compare low hands:
// (applicable only for a hand types that supports low hands)
if hand1.LowCompare(hand2) == 0 {
	fmt.Printf("%s and %s are equal!", hand1, hand2)
}

// Sort hands:
sort.Slice(hands, func(i, j int) bool {
	return hands[i].Compare(hands[j]) < 0
})
Ordering Hands

Order and LowOrder determine the winner(s) of a hand by ordering the indexes of a []*Hand and returning the list of ordered hands as a []int and an int pivot indicating the position within the returned list demarcating winning and losing hands.

A Hand whose index is in position i < pivot is considered to be the winner(s) of the hand. Hi hands are guaranteed to have 1 or more winner(s), while Lo hands have 0 or more winner(s):

// Order hands by lowest hand rank, low to high:
h, pivot := cardrank.Order(hands)
for i := 0; i < pivot; i++ {
	fmt.Printf("%s is a Hi winner!", hands[h[i]])
}

// Order low hands by lowest hand rank, low to high:
// (applicable only for a hand types that supports low hands)
l, pivot := cardrank.LowOrder(hands)
for i := 0; i < pivot; i++ {
	fmt.Printf("%s is a Lo winner!", hands[h[i]])
}

See the examples for an overview of using the package APIs for winner determination for the different Type of poker hands.

Build Tags

Build tags can be used with go build to change the package's build configuration. Available tags:

portable

The portable tag disables the TwoPlusTwo, in effect excluding the the large lookup table, and creating significantly smaller binaries but at the cost of more expensive poker hand rank evaluation. Useful when building for portable or embedded environments, such as a client application:

go build -tags portable
embedded

The embedded tag disables the CactusFast and the TwoPlusTwo, creating the smallest possible binaries. Useful when either embedding the package in another application, or in constrained runtime environments such as WASM:

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

The noinit tag disables the package level initialization. Useful when applications need the fastest possible startup times and can defer initialization, or when using a third-party algorithm:

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

When using the noinit build tag, the user will need to call the Init func to set DefaultCactus, DefaultRank and to register the default types automatically:

// Set DefaultCactus, DefaultRank based on available implementations:
cardrank.Init()

Alternatively, the DefaultCactus and DefaultRank can be set manually. After DefaultCactus and DefaultRank have been set, call RegisterDefaultTypes to register built in types:

// Set manually (such as when using a third-party implementation):
cardrank.DefaultCactus = cardrank.Cactus
cardrank.DefaultRank = cardrank.NewHandRank(cardrank.Cactus)

// Then call RegisterDefaultTypes to register default types
if err := cardrank.RegisterDefaultTypes(); err != nil {
	panic(err)
}
forcefat

The forcefat tag forces a "fat" binary build, including the TwoPlusTwo's large lookup table, irrespective of other build tags:

GOOS=js GOARCH=wasm go build -tags 'forcefat' -o cardrank.wasm

Future Development

Rank funcs for Kansas City Lowball, Sökö, and other poker variants will be added to this package in addition to standardized interfaces for managing poker tables and games.

Documentation

Overview

Package github.com/cardrank/cardrank is a library of types, utilities, and interfaces for working with playing cards, card decks, and evaluating poker hand ranks.

Supports Texas Holdem, Texas Holdem Short (6+), Texas Holdem Royal (10+), Omaha, Omaha Hi/Lo, Stud, Stud Hi/Lo, Razz, and Badugi.

Example (Badugi)
package main

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

	"github.com/cardrank/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.Badugi.Deal(rnd, game.players)
		hands := cardrank.Badugi.RankHands(pockets, nil)
		fmt.Printf("------ Badugi %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:

------ Badugi 1 ------
Player 1: [K♥ J♣ A♥ Q♠] Queen, Jack, Ace-low [Q♠ J♣ A♥] [K♥]
Player 2: [7♣ 4♣ 5♠ 2♠] Four, Two-low [4♣ 2♠] [7♣ 5♠]
Result:   Player 1 wins with Queen, Jack, Ace-low [Q♠ J♣ A♥]
------ Badugi 2 ------
Player 1: [3♠ 3♦ T♠ Q♠] Ten, Three-low [T♠ 3♦] [Q♠ 3♠]
Player 2: [6♦ Q♣ 8♥ 6♣] Queen, Eight, Six-low [Q♣ 8♥ 6♦] [6♣]
Player 3: [Q♦ K♠ 8♣ A♥] King, Queen, Eight, Ace-low [K♠ Q♦ 8♣ A♥] []
Player 4: [K♦ T♦ 8♦ 4♥] Eight, Four-low [8♦ 4♥] [K♦ T♦]
Player 5: [J♦ 2♥ Q♥ 6♠] Jack, Six, Two-low [J♦ 6♠ 2♥] [Q♥]
Result:   Player 3 wins with King, Queen, Eight, Ace-low [K♠ Q♦ 8♣ A♥]
------ Badugi 3 ------
Player 1: [K♠ Q♠ 4♣ J♦] Queen, Jack, Four-low [Q♠ J♦ 4♣] [K♠]
Player 2: [J♠ 3♣ 8♥ 2♠] Eight, Three, Two-low [8♥ 3♣ 2♠] [J♠]
Player 3: [3♠ T♠ 2♣ Q♦] Queen, Three, Two-low [Q♦ 3♠ 2♣] [T♠]
Player 4: [5♣ 5♥ T♦ 2♦] Five, Two-low [5♥ 2♦] [T♦ 5♣]
Player 5: [7♠ 3♥ 6♠ A♣] Six, Three, Ace-low [6♠ 3♥ A♣] [7♠]
Player 6: [4♠ 8♦ K♦ T♣] Ten, Eight, Four-low [T♣ 8♦ 4♠] [K♦]
Result:   Player 5 wins with Six, Three, Ace-low [6♠ 3♥ A♣]
------ Badugi 4 ------
Player 1: [6♠ K♥ A♣ 8♣] King, Six, Ace-low [K♥ 6♠ A♣] [8♣]
Player 2: [Q♥ 4♥ J♣ 5♥] Jack, Four-low [J♣ 4♥] [Q♥ 5♥]
Player 3: [2♣ 6♥ 5♣ Q♠] Queen, Six, Two-low [Q♠ 6♥ 2♣] [5♣]
Player 4: [9♠ J♥ K♠ J♠] Jack, Nine-low [J♥ 9♠] [K♠ J♠]
Player 5: [3♦ 4♦ K♣ 8♦] King, Three-low [K♣ 3♦] [8♦ 4♦]
Player 6: [T♣ Q♦ A♠ 7♥] Queen, Ten, Seven, Ace-low [Q♦ T♣ 7♥ A♠] []
Result:   Player 6 wins with Queen, Ten, Seven, Ace-low [Q♦ T♣ 7♥ A♠]
------ Badugi 5 ------
Player 1: [3♦ 4♦ 5♦ J♣] Jack, Three-low [J♣ 3♦] [5♦ 4♦]
Player 2: [T♥ J♠ K♠ 2♣] Jack, Ten, Two-low [J♠ T♥ 2♣] [K♠]
Player 3: [A♣ 9♠ T♠ 3♠] Three, Ace-low [3♠ A♣] [T♠ 9♠]
Player 4: [7♦ 3♣ 8♠ 7♣] Eight, Seven, Three-low [8♠ 7♦ 3♣] [7♣]
Player 5: [5♣ Q♠ J♥ 2♠] Jack, Five, Two-low [J♥ 5♣ 2♠] [Q♠]
Player 6: [6♠ 7♠ 7♥ 2♥] Six, Two-low [6♠ 2♥] [7♠ 7♥]
Result:   Player 4 wins with Eight, Seven, Three-low [8♠ 7♦ 3♣]
Example (Holdem)
package main

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

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

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

	"github.com/cardrank/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, 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♥ J♣ A♥ Q♠] Flush, Ace-high [A♥ K♥ 7♥ 5♥ 4♥] [J♣ Q♠ 3♥ K♣]
Player 2: [7♣ 4♣ 5♠ 2♠] Two Pair, Sevens over Fives, kicker King [7♣ 7♥ 5♥ 5♠ K♣] [4♣ 2♠ 3♥ 4♥]
Result:   Player 1 wins with Flush, Ace-high [A♥ K♥ 7♥ 5♥ 4♥]
------ Omaha 2 ------
Board:    [3♥ 7♣ 3♣ 9♠ 9♣]
Player 1: [3♠ 3♦ T♠ Q♠] Four of a Kind, Threes, kicker Nine [3♣ 3♦ 3♥ 3♠ 9♠] [T♠ Q♠ 7♣ 9♣]
Player 2: [6♦ Q♣ 8♥ 6♣] Flush, Queen-high [Q♣ 9♣ 7♣ 6♣ 3♣] [6♦ 8♥ 3♥ 9♠]
Player 3: [Q♦ K♠ 8♣ A♥] Pair, Nines, kickers Ace, King, Seven [9♣ 9♠ A♥ K♠ 7♣] [Q♦ 8♣ 3♥ 3♣]
Player 4: [K♦ T♦ 8♦ 4♥] Pair, Nines, kickers King, Ten, Seven [9♣ 9♠ K♦ T♦ 7♣] [8♦ 4♥ 3♥ 3♣]
Player 5: [J♦ 2♥ Q♥ 6♠] Pair, Nines, kickers Queen, Jack, Seven [9♣ 9♠ Q♥ J♦ 7♣] [2♥ 6♠ 3♥ 3♣]
Result:   Player 1 wins with Four of a Kind, Threes, kicker Nine [3♣ 3♦ 3♥ 3♠ 9♠]
------ Omaha 3 ------
Board:    [J♣ T♥ 4♥ K♣ Q♣]
Player 1: [K♠ Q♠ 4♣ J♦] Two Pair, Kings over Queens, kicker Jack [K♣ K♠ Q♣ Q♠ J♣] [4♣ J♦ T♥ 4♥]
Player 2: [J♠ 3♣ 8♥ 2♠] Pair, Jacks, kickers King, Queen, Eight [J♣ J♠ K♣ Q♣ 8♥] [3♣ 2♠ T♥ 4♥]
Player 3: [3♠ T♠ 2♣ Q♦] Two Pair, Queens over Tens, kicker King [Q♣ Q♦ T♥ T♠ K♣] [3♠ 2♣ J♣ 4♥]
Player 4: [5♣ 5♥ T♦ 2♦] Pair, Tens, kickers King, Queen, Five [T♦ T♥ K♣ Q♣ 5♣] [5♥ 2♦ J♣ 4♥]
Player 5: [7♠ 3♥ 6♠ A♣] Nothing, Ace-high, kickers King, Queen, Jack, Seven [A♣ K♣ Q♣ J♣ 7♠] [3♥ 6♠ T♥ 4♥]
Player 6: [4♠ 8♦ K♦ T♣] Two Pair, Kings over Tens, kicker Queen [K♣ K♦ T♣ T♥ Q♣] [4♠ 8♦ J♣ 4♥]
Result:   Player 1 wins with Two Pair, Kings over Queens, kicker Jack [K♣ K♠ Q♣ Q♠ J♣]
------ Omaha 4 ------
Board:    [2♦ 6♦ 6♣ Q♣ 7♣]
Player 1: [6♠ K♥ A♣ 8♣] Flush, Ace-high [A♣ Q♣ 8♣ 7♣ 6♣] [6♠ K♥ 2♦ 6♦]
Player 2: [Q♥ 4♥ J♣ 5♥] Two Pair, Queens over Sixes, kicker Jack [Q♣ Q♥ 6♣ 6♦ J♣] [4♥ 5♥ 2♦ 7♣]
Player 3: [2♣ 6♥ 5♣ Q♠] Full House, Sixes full of Queens [6♣ 6♦ 6♥ Q♣ Q♠] [2♣ 5♣ 2♦ 7♣]
Player 4: [9♠ J♥ K♠ J♠] Two Pair, Jacks over Sixes, kicker Queen [J♥ J♠ 6♣ 6♦ Q♣] [9♠ K♠ 2♦ 7♣]
Player 5: [3♦ 4♦ K♣ 8♦] Pair, Sixes, kickers King, Queen, Eight [6♣ 6♦ K♣ Q♣ 8♦] [3♦ 4♦ 2♦ 7♣]
Player 6: [T♣ Q♦ A♠ 7♥] Two Pair, Queens over Sevens, kicker Six [Q♣ Q♦ 7♣ 7♥ 6♦] [T♣ A♠ 2♦ 6♣]
Result:   Player 3 wins with Full House, Sixes full of Queens [6♣ 6♦ 6♥ Q♣ Q♠]
------ Omaha 5 ------
Board:    [4♣ K♣ 6♦ 9♦ 5♠]
Player 1: [3♦ 4♦ 5♦ J♣] Two Pair, Fives over Fours, kicker King [5♦ 5♠ 4♣ 4♦ K♣] [3♦ J♣ 6♦ 9♦]
Player 2: [T♥ J♠ K♠ 2♣] Pair, Kings, kickers Jack, Nine, Six [K♣ K♠ J♠ 9♦ 6♦] [T♥ 2♣ 4♣ 5♠]
Player 3: [A♣ 9♠ T♠ 3♠] Pair, Nines, kickers Ace, King, Six [9♦ 9♠ A♣ K♣ 6♦] [T♠ 3♠ 4♣ 5♠]
Player 4: [7♦ 3♣ 8♠ 7♣] Straight, Nine-high [9♦ 8♠ 7♦ 6♦ 5♠] [3♣ 7♣ 4♣ K♣]
Player 5: [5♣ Q♠ J♥ 2♠] Pair, Fives, kickers King, Queen, Nine [5♣ 5♠ K♣ Q♠ 9♦] [J♥ 2♠ 4♣ 6♦]
Player 6: [6♠ 7♠ 7♥ 2♥] Pair, Sevens, kickers King, Nine, Six [7♥ 7♠ K♣ 9♦ 6♦] [6♠ 2♥ 4♣ 5♠]
Result:   Player 4 wins with Straight, Nine-high [9♦ 8♠ 7♦ 6♦ 5♠]
Example (OmahaHiLo)
package main

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

	"github.com/cardrank/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, 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())
			fmt.Printf("  Lo: %s %b %b\n", hands[j].LowDescription(), hands[j].LowBest(), hands[j].LowUnused())
		}
		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♥ J♣ A♥ Q♠]
  Hi: Flush, Ace-high [A♥ K♥ 7♥ 5♥ 4♥] [J♣ Q♠ 3♥ K♣]
  Lo: None [] []
Player 2: [7♣ 4♣ 5♠ 2♠]
  Hi: Two Pair, Sevens over Fives, kicker King [7♣ 7♥ 5♥ 5♠ K♣] [4♣ 2♠ 3♥ 4♥]
  Lo: Seven, Five, Four, Three, Two-low [7♣ 5♥ 4♥ 3♥ 2♠] [4♣ 5♠ 7♥ K♣]
Result (Hi): Player 1 wins with Flush, Ace-high [A♥ K♥ 7♥ 5♥ 4♥]
Result (Lo): Player 2 wins with Seven, Five, Four, Three, Two-low [7♣ 5♥ 4♥ 3♥ 2♠]
------ OmahaHiLo 2 ------
Board: [3♥ 7♣ 3♣ 9♠ 9♣]
Player 1: [3♠ 3♦ T♠ Q♠]
  Hi: Four of a Kind, Threes, kicker Nine [3♣ 3♦ 3♥ 3♠ 9♠] [T♠ Q♠ 7♣ 9♣]
  Lo: None [] []
Player 2: [6♦ Q♣ 8♥ 6♣]
  Hi: Flush, Queen-high [Q♣ 9♣ 7♣ 6♣ 3♣] [6♦ 8♥ 3♥ 9♠]
  Lo: None [] []
Player 3: [Q♦ K♠ 8♣ A♥]
  Hi: Pair, Nines, kickers Ace, King, Seven [9♣ 9♠ A♥ K♠ 7♣] [Q♦ 8♣ 3♥ 3♣]
  Lo: None [] []
Player 4: [K♦ T♦ 8♦ 4♥]
  Hi: Pair, Nines, kickers King, Ten, Seven [9♣ 9♠ K♦ T♦ 7♣] [8♦ 4♥ 3♥ 3♣]
  Lo: None [] []
Player 5: [J♦ 2♥ Q♥ 6♠]
  Hi: Pair, Nines, kickers Queen, Jack, Seven [9♣ 9♠ Q♥ J♦ 7♣] [2♥ 6♠ 3♥ 3♣]
  Lo: None [] []
Result (Hi): Player 1 scoops with Four of a Kind, Threes, kicker Nine [3♣ 3♦ 3♥ 3♠ 9♠]
Result (Lo): no player made a low hand
------ OmahaHiLo 3 ------
Board: [J♣ T♥ 4♥ K♣ Q♣]
Player 1: [K♠ Q♠ 4♣ J♦]
  Hi: Two Pair, Kings over Queens, kicker Jack [K♣ K♠ Q♣ Q♠ J♣] [4♣ J♦ T♥ 4♥]
  Lo: None [] []
Player 2: [J♠ 3♣ 8♥ 2♠]
  Hi: Pair, Jacks, kickers King, Queen, Eight [J♣ J♠ K♣ Q♣ 8♥] [3♣ 2♠ T♥ 4♥]
  Lo: None [] []
Player 3: [3♠ T♠ 2♣ Q♦]
  Hi: Two Pair, Queens over Tens, kicker King [Q♣ Q♦ T♥ T♠ K♣] [3♠ 2♣ J♣ 4♥]
  Lo: None [] []
Player 4: [5♣ 5♥ T♦ 2♦]
  Hi: Pair, Tens, kickers King, Queen, Five [T♦ T♥ K♣ Q♣ 5♣] [5♥ 2♦ J♣ 4♥]
  Lo: None [] []
Player 5: [7♠ 3♥ 6♠ A♣]
  Hi: Nothing, Ace-high, kickers King, Queen, Jack, Seven [A♣ K♣ Q♣ J♣ 7♠] [3♥ 6♠ T♥ 4♥]
  Lo: None [] []
Player 6: [4♠ 8♦ K♦ T♣]
  Hi: Two Pair, Kings over Tens, kicker Queen [K♣ K♦ T♣ T♥ Q♣] [4♠ 8♦ J♣ 4♥]
  Lo: None [] []
Result (Hi): Player 1 scoops with Two Pair, Kings over Queens, kicker Jack [K♣ K♠ Q♣ Q♠ J♣]
Result (Lo): no player made a low hand
------ OmahaHiLo 4 ------
Board: [2♦ 6♦ 6♣ Q♣ 7♣]
Player 1: [6♠ K♥ A♣ 8♣]
  Hi: Flush, Ace-high [A♣ Q♣ 8♣ 7♣ 6♣] [6♠ K♥ 2♦ 6♦]
  Lo: Eight, Seven, Six, Two, Ace-low [8♣ 7♣ 6♦ 2♦ A♣] [6♠ K♥ 6♣ Q♣]
Player 2: [Q♥ 4♥ J♣ 5♥]
  Hi: Two Pair, Queens over Sixes, kicker Jack [Q♣ Q♥ 6♣ 6♦ J♣] [4♥ 5♥ 2♦ 7♣]
  Lo: Seven, Six, Five, Four, Two-low [7♣ 6♦ 5♥ 4♥ 2♦] [Q♥ J♣ 6♣ Q♣]
Player 3: [2♣ 6♥ 5♣ Q♠]
  Hi: Full House, Sixes full of Queens [6♣ 6♦ 6♥ Q♣ Q♠] [2♣ 5♣ 2♦ 7♣]
  Lo: None [] []
Player 4: [9♠ J♥ K♠ J♠]
  Hi: Two Pair, Jacks over Sixes, kicker Queen [J♥ J♠ 6♣ 6♦ Q♣] [9♠ K♠ 2♦ 7♣]
  Lo: None [] []
Player 5: [3♦ 4♦ K♣ 8♦]
  Hi: Pair, Sixes, kickers King, Queen, Eight [6♣ 6♦ K♣ Q♣ 8♦] [3♦ 4♦ 2♦ 7♣]
  Lo: Seven, Six, Four, Three, Two-low [7♣ 6♦ 4♦ 3♦ 2♦] [K♣ 8♦ 6♣ Q♣]
Player 6: [T♣ Q♦ A♠ 7♥]
  Hi: Two Pair, Queens over Sevens, kicker Six [Q♣ Q♦ 7♣ 7♥ 6♦] [T♣ A♠ 2♦ 6♣]
  Lo: None [] []
Result (Hi): Player 3 wins with Full House, Sixes full of Queens [6♣ 6♦ 6♥ Q♣ Q♠]
Result (Lo): Player 5 wins with Seven, Six, Four, Three, Two-low [7♣ 6♦ 4♦ 3♦ 2♦]
------ OmahaHiLo 5 ------
Board: [4♣ K♣ 6♦ 9♦ 5♠]
Player 1: [3♦ 4♦ 5♦ J♣]
  Hi: Two Pair, Fives over Fours, kicker King [5♦ 5♠ 4♣ 4♦ K♣] [3♦ J♣ 6♦ 9♦]
  Lo: None [] []
Player 2: [T♥ J♠ K♠ 2♣]
  Hi: Pair, Kings, kickers Jack, Nine, Six [K♣ K♠ J♠ 9♦ 6♦] [T♥ 2♣ 4♣ 5♠]
  Lo: None [] []
Player 3: [A♣ 9♠ T♠ 3♠]
  Hi: Pair, Nines, kickers Ace, King, Six [9♦ 9♠ A♣ K♣ 6♦] [T♠ 3♠ 4♣ 5♠]
  Lo: Six, Five, Four, Three, Ace-low [6♦ 5♠ 4♣ 3♠ A♣] [9♠ T♠ K♣ 9♦]
Player 4: [7♦ 3♣ 8♠ 7♣]
  Hi: Straight, Nine-high [9♦ 8♠ 7♦ 6♦ 5♠] [3♣ 7♣ 4♣ K♣]
  Lo: Seven, Six, Five, Four, Three-low [7♦ 6♦ 5♠ 4♣ 3♣] [8♠ 7♣ K♣ 9♦]
Player 5: [5♣ Q♠ J♥ 2♠]
  Hi: Pair, Fives, kickers King, Queen, Nine [5♣ 5♠ K♣ Q♠ 9♦] [J♥ 2♠ 4♣ 6♦]
  Lo: None [] []
Player 6: [6♠ 7♠ 7♥ 2♥]
  Hi: Pair, Sevens, kickers King, Nine, Six [7♥ 7♠ K♣ 9♦ 6♦] [6♠ 2♥ 4♣ 5♠]
  Lo: Seven, Six, Five, Four, Two-low [7♠ 6♦ 5♠ 4♣ 2♥] [6♠ 7♥ K♣ 9♦]
Result (Hi): Player 4 wins with Straight, Nine-high [9♦ 8♠ 7♦ 6♦ 5♠]
Result (Lo): Player 3 wins with Six, Five, Four, Three, Ace-low [6♦ 5♠ 4♣ 3♠ A♣]
Example (OmahaMultiBoard)
package main

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

	"github.com/cardrank/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))
		deck := cardrank.Omaha.Deck()
		deck.Shuffle(rnd)
		pockets := deck.Deal(game.players, 4)
		boards := deck.MultiBoard(2, 1, 3, 1, 1)
		fmt.Printf("------ Omaha MultiBoard %d ------\n", i+1)
		for j := 0; j < len(boards); j++ {
			fmt.Printf("Board %d:    %b\n", j+1, boards[j])
			hands := cardrank.Omaha.RankHands(pockets, boards[j])
			for k := 0; k < game.players; k++ {
				fmt.Printf("  Player %d: %b %s %b %b\n", k+1, hands[k].Pocket, hands[k].Description(), hands[k].Best(), hands[k].Unused())
			}
			h, pivot := cardrank.Order(hands)
			if pivot == 1 {
				fmt.Printf("Result %d:   Player %d wins with %s %b\n", j+1, 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 %d:   Players %s push with %s %s\n", j+1, strings.Join(s, ", "), hands[h[0]].Description(), strings.Join(b, ", "))
			}
		}
	}
}
Output:

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

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

	"github.com/cardrank/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.Razz.Deal(rnd, 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:

------ Razz 1 ------
Player 1: [K♥ J♣ A♥ Q♠ 6♣ 5♥ Q♦] Queen, Jack, Six, Five, Ace-low [Q♠ J♣ 6♣ 5♥ A♥] [K♥ Q♦]
Player 2: [7♣ 4♣ 5♠ 2♠ 3♥ 4♥ 7♥] Seven, Five, Four, Three, Two-low [7♣ 5♠ 4♣ 3♥ 2♠] [4♥ 7♥]
Result:   Player 2 wins with Seven, Five, Four, Three, Two-low [7♣ 5♠ 4♣ 3♥ 2♠]
------ Razz 2 ------
Player 1: [3♠ 3♦ T♠ Q♠ T♥ 9♠ K♥] King, Queen, Ten, Nine, Three-low [K♥ Q♠ T♠ 9♠ 3♠] [3♦ T♥]
Player 2: [6♦ Q♣ 8♥ 6♣ 3♥ T♣ 7♥] Ten, Eight, Seven, Six, Three-low [T♣ 8♥ 7♥ 6♦ 3♥] [Q♣ 6♣]
Player 3: [Q♦ K♠ 8♣ A♥ 7♣ 9♣ 2♣] Nine, Eight, Seven, Two, Ace-low [9♣ 8♣ 7♣ 2♣ A♥] [Q♦ K♠]
Player 4: [K♦ T♦ 8♦ 4♥ 3♣ J♠ 2♦] Ten, Eight, Four, Three, Two-low [T♦ 8♦ 4♥ 3♣ 2♦] [K♦ J♠]
Player 5: [J♦ 2♥ Q♥ 6♠ 5♦ 7♠ A♦] Seven, Six, Five, Two, Ace-low [7♠ 6♠ 5♦ 2♥ A♦] [J♦ Q♥]
Result:   Player 5 wins with Seven, Six, Five, Two, Ace-low [7♠ 6♠ 5♦ 2♥ A♦]
------ Razz 3 ------
Player 1: [K♠ Q♠ 4♣ J♦ 7♥ 7♣ J♥] King, Queen, Jack, Seven, Four-low [K♠ Q♠ J♦ 7♥ 4♣] [7♣ J♥]
Player 2: [J♠ 3♣ 8♥ 2♠ J♣ Q♣ 7♦] Jack, Eight, Seven, Three, Two-low [J♠ 8♥ 7♦ 3♣ 2♠] [J♣ Q♣]
Player 3: [3♠ T♠ 2♣ Q♦ T♥ K♥ 3♦] King, Queen, Ten, Three, Two-low [K♥ Q♦ T♠ 3♠ 2♣] [T♥ 3♦]
Player 4: [5♣ 5♥ T♦ 2♦ 4♥ 9♦ 2♥] Ten, Nine, Five, Four, Two-low [T♦ 9♦ 5♣ 4♥ 2♦] [5♥ 2♥]
Player 5: [7♠ 3♥ 6♠ A♣ 8♠ 6♦ A♦] Eight, Seven, Six, Three, Ace-low [8♠ 7♠ 6♠ 3♥ A♣] [6♦ A♦]
Player 6: [4♠ 8♦ K♦ T♣ K♣ 5♠ 9♣] Ten, Nine, Eight, Five, Four-low [T♣ 9♣ 8♦ 5♠ 4♠] [K♦ K♣]
Result:   Player 5 wins with Eight, Seven, Six, Three, Ace-low [8♠ 7♠ 6♠ 3♥ A♣]
------ Razz 4 ------
Player 1: [6♠ K♥ A♣ 8♣ 2♠ 5♦ A♥] Eight, Six, Five, Two, Ace-low [8♣ 6♠ 5♦ 2♠ A♣] [K♥ A♥]
Player 2: [Q♥ 4♥ J♣ 5♥ 2♦ 7♣ 3♠] Seven, Five, Four, Three, Two-low [7♣ 5♥ 4♥ 3♠ 2♦] [Q♥ J♣]
Player 3: [2♣ 6♥ 5♣ Q♠ 6♦ 9♥ 3♣] Nine, Six, Five, Three, Two-low [9♥ 6♥ 5♣ 3♣ 2♣] [Q♠ 6♦]
Player 4: [9♠ J♥ K♠ J♠ 6♣ K♦ T♠] King, Jack, Ten, Nine, Six-low [K♠ J♥ T♠ 9♠ 6♣] [J♠ K♦]
Player 5: [3♦ 4♦ K♣ 8♦ 8♥ 9♣ T♥] Ten, Nine, Eight, Four, Three-low [T♥ 9♣ 8♦ 4♦ 3♦] [K♣ 8♥]
Player 6: [T♣ Q♦ A♠ 7♥ Q♣ 7♦ 2♥] Queen, Ten, Seven, Two, Ace-low [Q♦ T♣ 7♥ 2♥ A♠] [Q♣ 7♦]
Result:   Player 2 wins with Seven, Five, Four, Three, Two-low [7♣ 5♥ 4♥ 3♠ 2♦]
------ Razz 5 ------
Player 1: [3♦ 4♦ 5♦ J♣ 4♥ K♥ 8♣] Jack, Eight, Five, Four, Three-low [J♣ 8♣ 5♦ 4♦ 3♦] [4♥ K♥]
Player 2: [T♥ J♠ K♠ 2♣ 4♣ 5♠ 2♦] Jack, Ten, Five, Four, Two-low [J♠ T♥ 5♠ 4♣ 2♣] [K♠ 2♦]
Player 3: [A♣ 9♠ T♠ 3♠ K♣ 8♦ A♥] Ten, Nine, Eight, Three, Ace-low [T♠ 9♠ 8♦ 3♠ A♣] [K♣ A♥]
Player 4: [7♦ 3♣ 8♠ 7♣ 6♦ 6♥ 6♣] Pair, Sixes, kickers Eight, Seven, Three [6♦ 6♥ 8♠ 7♦ 3♣] [7♣ 6♣]
Player 5: [5♣ Q♠ J♥ 2♠ A♠ 8♥ 4♠] Eight, Five, Four, Two, Ace-low [8♥ 5♣ 4♠ 2♠ A♠] [Q♠ J♥]
Player 6: [6♠ 7♠ 7♥ 2♥ 9♦ K♦ T♦] Ten, Nine, Seven, Six, Two-low [T♦ 9♦ 7♠ 6♠ 2♥] [7♥ K♦]
Result:   Player 5 wins with Eight, Five, Four, Two, Ace-low [8♥ 5♣ 4♠ 2♠ A♠]
Example (Royal)
package main

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

	"github.com/cardrank/cardrank"
)

func main() {
	for i, game := range []struct {
		seed    int64
		players int
	}{
		{119, 2},
		{155, 3},
		{384, 4},
		{880, 5},
		{3453, 2},
		{5662, 3},
		{65481, 4},
		{27947, 5},
	} {
		// note: use a real random source
		rnd := rand.New(rand.NewSource(game.seed))
		pockets, board := cardrank.Royal.Deal(rnd, game.players)
		hands := cardrank.Royal.RankHands(pockets, board)
		fmt.Printf("------ Royal %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:

------ Royal 1 ------
Board:    [K♦ A♦ T♥ T♣ J♠]
Player 1: [A♠ T♠] Full House, Tens full of Aces [T♣ T♥ T♠ A♦ A♠] [K♦ J♠]
Player 2: [A♥ K♠] Two Pair, Aces over Kings, kicker Jack [A♦ A♥ K♦ K♠ J♠] [T♣ T♥]
Result:   Player 1 wins with Full House, Tens full of Aces [T♣ T♥ T♠ A♦ A♠]
------ Royal 2 ------
Board:    [A♣ K♠ J♦ Q♣ J♣]
Player 1: [A♠ Q♠] Two Pair, Aces over Queens, kicker King [A♣ A♠ Q♣ Q♠ K♠] [J♣ J♦]
Player 2: [T♠ J♥] Straight, Ace-high [A♣ K♠ Q♣ J♣ T♠] [J♦ J♥]
Player 3: [K♣ T♥] Straight, Ace-high [A♣ K♣ Q♣ J♣ T♥] [K♠ J♦]
Result:   Players 2, 3 push with Straight, Ace-high [A♣ K♠ Q♣ J♣ T♠], [A♣ K♣ Q♣ J♣ T♥]
------ Royal 3 ------
Board:    [K♠ T♦ T♣ Q♦ A♥]
Player 1: [T♠ T♥] Four of a Kind, Tens, kicker Ace [T♣ T♦ T♥ T♠ A♥] [K♠ Q♦]
Player 2: [J♣ Q♣] Straight, Ace-high [A♥ K♠ Q♣ J♣ T♣] [Q♦ T♦]
Player 3: [A♦ K♦] Two Pair, Aces over Kings, kicker Queen [A♦ A♥ K♦ K♠ Q♦] [T♣ T♦]
Player 4: [K♥ K♣] Full House, Kings full of Tens [K♣ K♥ K♠ T♣ T♦] [A♥ Q♦]
Result:   Player 1 wins with Four of a Kind, Tens, kicker Ace [T♣ T♦ T♥ T♠ A♥]
------ Royal 4 ------
Board:    [J♥ A♠ T♥ T♣ K♠]
Player 1: [Q♦ T♠] Straight, Ace-high [A♠ K♠ Q♦ J♥ T♣] [T♥ T♠]
Player 2: [K♥ T♦] Full House, Tens full of Kings [T♣ T♦ T♥ K♥ K♠] [A♠ J♥]
Player 3: [A♣ Q♠] Straight, Ace-high [A♣ K♠ Q♠ J♥ T♣] [A♠ T♥]
Player 4: [A♦ J♠] Two Pair, Aces over Jacks, kicker King [A♦ A♠ J♥ J♠ K♠] [T♣ T♥]
Player 5: [K♦ J♦] Two Pair, Kings over Jacks, kicker Ace [K♦ K♠ J♦ J♥ A♠] [T♣ T♥]
Result:   Player 2 wins with Full House, Tens full of Kings [T♣ T♦ T♥ K♥ K♠]
------ Royal 5 ------
Board:    [J♣ K♥ K♠ J♥ Q♣]
Player 1: [A♥ T♦] Straight, Ace-high [A♥ K♥ Q♣ J♣ T♦] [K♠ J♥]
Player 2: [J♦ Q♠] Full House, Jacks full of Kings [J♣ J♦ J♥ K♥ K♠] [Q♣ Q♠]
Result:   Player 2 wins with Full House, Jacks full of Kings [J♣ J♦ J♥ K♥ K♠]
------ Royal 6 ------
Board:    [K♥ A♠ K♦ K♠ A♣]
Player 1: [J♥ J♠] Full House, Kings full of Aces [K♦ K♥ K♠ A♣ A♠] [J♥ J♠]
Player 2: [Q♦ A♥] Full House, Aces full of Kings [A♣ A♥ A♠ K♦ K♥] [K♠ Q♦]
Player 3: [Q♠ T♣] Full House, Kings full of Aces [K♦ K♥ K♠ A♣ A♠] [Q♠ T♣]
Result:   Player 2 wins with Full House, Aces full of Kings [A♣ A♥ A♠ K♦ K♥]
------ Royal 7 ------
Board:    [J♥ T♦ Q♠ K♣ K♥]
Player 1: [K♦ J♣] Full House, Kings full of Jacks [K♣ K♦ K♥ J♣ J♥] [Q♠ T♦]
Player 2: [T♥ T♠] Full House, Tens full of Kings [T♦ T♥ T♠ K♣ K♥] [Q♠ J♥]
Player 3: [A♠ A♥] Straight, Ace-high [A♥ K♣ Q♠ J♥ T♦] [A♠ K♥]
Player 4: [Q♣ A♦] Straight, Ace-high [A♦ K♣ Q♣ J♥ T♦] [K♥ Q♠]
Result:   Player 1 wins with Full House, Kings full of Jacks [K♣ K♦ K♥ J♣ J♥]
------ Royal 8 ------
Board:    [A♠ K♦ Q♦ A♦ A♣]
Player 1: [Q♠ J♠] Full House, Aces full of Queens [A♣ A♦ A♠ Q♦ Q♠] [K♦ J♠]
Player 2: [T♦ A♥] Four of a Kind, Aces, kicker King [A♣ A♦ A♥ A♠ K♦] [Q♦ T♦]
Player 3: [J♥ K♠] Full House, Aces full of Kings [A♣ A♦ A♠ K♦ K♠] [Q♦ J♥]
Player 4: [Q♥ J♦] Full House, Aces full of Queens [A♣ A♦ A♠ Q♦ Q♥] [K♦ J♦]
Player 5: [K♣ T♥] Full House, Aces full of Kings [A♣ A♦ A♠ K♣ K♦] [Q♦ T♥]
Result:   Player 2 wins with Four of a Kind, Aces, kicker King [A♣ A♦ A♥ A♠ K♦]
Example (Short)
package main

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

	"github.com/cardrank/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.Short.Deal(rnd, game.players)
		hands := cardrank.Short.RankHands(pockets, board)
		fmt.Printf("------ Short %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:

------ Short 1 ------
Board:    [9♥ A♦ A♥ 8♣ A♣]
Player 1: [8♥ A♠] Four of a Kind, Aces, kicker Eight [A♣ A♦ A♥ A♠ 8♣] [8♥ 9♥]
Player 2: [7♥ J♦] Three of a Kind, Aces, kickers Jack, Nine [A♣ A♦ A♥ J♦ 9♥] [8♣ 7♥]
Result:   Player 1 wins with Four of a Kind, Aces, kicker Eight [A♣ A♦ A♥ A♠ 8♣]
------ Short 2 ------
Board:    [9♣ 6♦ A♠ J♠ 6♠]
Player 1: [T♥ A♣] Two Pair, Aces over Sixes, kicker Jack [A♣ A♠ 6♦ 6♠ J♠] [T♥ 9♣]
Player 2: [6♣ 7♣] Three of a Kind, Sixes, kickers Ace, Jack [6♣ 6♦ 6♠ A♠ J♠] [9♣ 7♣]
Player 3: [6♥ T♠] Three of a Kind, Sixes, kickers Ace, Jack [6♦ 6♥ 6♠ A♠ J♠] [T♠ 9♣]
Player 4: [9♥ K♠] Two Pair, Nines over Sixes, kicker Ace [9♣ 9♥ 6♦ 6♠ A♠] [K♠ J♠]
Result:   Players 2, 3 push with Three of a Kind, Sixes, kickers Ace, Jack [6♣ 6♦ 6♠ A♠ J♠], [6♦ 6♥ 6♠ A♠ J♠]
------ Short 3 ------
Board:    [T♥ J♣ 7♥ 9♥ K♣]
Player 1: [8♥ T♣] Straight, Jack-high [J♣ T♣ 9♥ 8♥ 7♥] [K♣ T♥]
Player 2: [T♠ Q♠] Straight, King-high [K♣ Q♠ J♣ T♥ 9♥] [T♠ 7♥]
Player 3: [J♠ 7♣] Two Pair, Jacks over Sevens, kicker King [J♣ J♠ 7♣ 7♥ K♣] [T♥ 9♥]
Player 4: [6♣ Q♦] Straight, King-high [K♣ Q♦ J♣ T♥ 9♥] [7♥ 6♣]
Player 5: [7♦ 6♠] Pair, Sevens, kickers King, Jack, Ten [7♦ 7♥ K♣ J♣ T♥] [9♥ 6♠]
Player 6: [8♠ 8♦] Straight, Jack-high [J♣ T♥ 9♥ 8♦ 7♥] [K♣ 8♠]
Player 7: [9♣ K♥] Two Pair, Kings over Nines, kicker Jack [K♣ K♥ 9♣ 9♥ J♣] [T♥ 7♥]
Player 8: [A♥ K♦] Pair, Kings, kickers Ace, Jack, Ten [K♣ K♦ A♥ J♣ T♥] [9♥ 7♥]
Result:   Players 2, 4 push with Straight, King-high [K♣ Q♠ J♣ T♥ 9♥], [K♣ Q♦ J♣ T♥ 9♥]
------ Short 4 ------
Board:    [T♦ 9♣ 9♦ Q♦ 8♦]
Player 1: [J♠ 9♥] Straight, Queen-high [Q♦ J♠ T♦ 9♣ 8♦] [9♦ 9♥]
Player 2: [T♥ 8♠] Two Pair, Tens over Nines, kicker Queen [T♦ T♥ 9♣ 9♦ Q♦] [8♦ 8♠]
Player 3: [6♣ J♦] Straight Flush, Queen-high [Q♦ J♦ T♦ 9♦ 8♦] [9♣ 6♣]
Player 4: [A♣ A♦] Flush, Ace-high [A♦ Q♦ T♦ 9♦ 8♦] [A♣ 9♣]
Result:   Player 3 wins with Straight Flush, Queen-high [Q♦ J♦ T♦ 9♦ 8♦]
------ Short 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: [T♠ K♠] Two Pair, Aces over Sixes, kicker King [A♣ A♠ 6♦ 6♠ K♠] [T♠ 7♦]
Player 3: [J♥ A♥] Full House, Aces full of Sixes [A♣ A♥ A♠ 6♦ 6♠] [J♥ 7♦]
Result:   Player 3 wins with Full House, Aces full of Sixes [A♣ A♥ A♠ 6♦ 6♠]
------ Short 6 ------
Board:    [A♣ 6♣ 9♣ T♦ 8♣]
Player 1: [6♥ 9♠] Two Pair, Nines over Sixes, kicker Ace [9♣ 9♠ 6♣ 6♥ A♣] [T♦ 8♣]
Player 2: [7♣ J♥] Straight Flush, Nine-high, Iron Maiden [9♣ 8♣ 7♣ 6♣ A♣] [J♥ T♦]
Player 3: [6♠ Q♠] Pair, Sixes, kickers Ace, Queen, Ten [6♣ 6♠ A♣ Q♠ T♦] [9♣ 8♣]
Result:   Player 2 wins with Straight Flush, Nine-high, Iron Maiden [9♣ 8♣ 7♣ 6♣ A♣]
------ Short 7 ------
Board:    [K♥ K♦ K♠ K♣ J♣]
Player 1: [7♦ 8♦] Four of a Kind, Kings, kicker Jack [K♣ K♦ K♥ K♠ J♣] [8♦ 7♦]
Player 2: [T♦ 6♥] Four of a Kind, Kings, kicker Jack [K♣ K♦ K♥ K♠ J♣] [T♦ 6♥]
Result:   Players 1, 2 push with Four of a Kind, Kings, kicker Jack [K♣ K♦ K♥ K♠ J♣], [K♣ K♦ K♥ K♠ J♣]
------ Short 8 ------
Board:    [8♦ 8♥ 8♠ Q♠ T♦]
Player 1: [J♦ 9♣] Straight, Queen-high [Q♠ J♦ T♦ 9♣ 8♦] [8♥ 8♠]
Player 2: [T♣ J♣] Full House, Eights full of Tens [8♦ 8♥ 8♠ T♣ T♦] [Q♠ J♣]
Player 3: [K♠ T♥] Full House, Eights full of Tens [8♦ 8♥ 8♠ T♦ T♥] [K♠ Q♠]
Player 4: [T♠ 7♥] Full House, Eights full of Tens [8♦ 8♥ 8♠ T♦ T♠] [Q♠ 7♥]
Result:   Players 2, 3, 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"

	"github.com/cardrank/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, 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♥ J♣ A♥ Q♠ 6♣ 5♥ Q♦] Pair, Queens, kickers Ace, King, Jack [Q♦ Q♠ A♥ K♥ J♣] [6♣ 5♥]
Player 2: [7♣ 4♣ 5♠ 2♠ 3♥ 4♥ 7♥] Two Pair, Sevens over Fours, kicker Five [7♣ 7♥ 4♣ 4♥ 5♠] [3♥ 2♠]
Result:   Player 2 wins with Two Pair, Sevens over Fours, kicker Five [7♣ 7♥ 4♣ 4♥ 5♠]
------ Stud 2 ------
Player 1: [3♠ 3♦ T♠ Q♠ T♥ 9♠ K♥] Two Pair, Tens over Threes, kicker King [T♥ T♠ 3♦ 3♠ K♥] [Q♠ 9♠]
Player 2: [6♦ Q♣ 8♥ 6♣ 3♥ T♣ 7♥] Pair, Sixes, kickers Queen, Ten, Eight [6♣ 6♦ Q♣ T♣ 8♥] [7♥ 3♥]
Player 3: [Q♦ K♠ 8♣ A♥ 7♣ 9♣ 2♣] Nothing, Ace-high, kickers King, Queen, Nine, Eight [A♥ K♠ Q♦ 9♣ 8♣] [7♣ 2♣]
Player 4: [K♦ T♦ 8♦ 4♥ 3♣ J♠ 2♦] Nothing, King-high, kickers Jack, Ten, Eight, Four [K♦ J♠ T♦ 8♦ 4♥] [3♣ 2♦]
Player 5: [J♦ 2♥ Q♥ 6♠ 5♦ 7♠ A♦] Nothing, Ace-high, kickers Queen, Jack, Seven, Six [A♦ Q♥ J♦ 7♠ 6♠] [5♦ 2♥]
Result:   Player 1 wins with Two Pair, Tens over Threes, kicker King [T♥ T♠ 3♦ 3♠ K♥]
------ Stud 3 ------
Player 1: [K♠ Q♠ 4♣ J♦ 7♥ 7♣ J♥] Two Pair, Jacks over Sevens, kicker King [J♦ J♥ 7♣ 7♥ K♠] [Q♠ 4♣]
Player 2: [J♠ 3♣ 8♥ 2♠ J♣ Q♣ 7♦] Pair, Jacks, kickers Queen, Eight, Seven [J♣ J♠ Q♣ 8♥ 7♦] [3♣ 2♠]
Player 3: [3♠ T♠ 2♣ Q♦ T♥ K♥ 3♦] Two Pair, Tens over Threes, kicker King [T♥ T♠ 3♦ 3♠ K♥] [Q♦ 2♣]
Player 4: [5♣ 5♥ T♦ 2♦ 4♥ 9♦ 2♥] Two Pair, Fives over Twos, kicker Ten [5♣ 5♥ 2♦ 2♥ T♦] [9♦ 4♥]
Player 5: [7♠ 3♥ 6♠ A♣ 8♠ 6♦ A♦] Two Pair, Aces over Sixes, kicker Eight [A♣ A♦ 6♦ 6♠ 8♠] [7♠ 3♥]
Player 6: [4♠ 8♦ K♦ T♣ K♣ 5♠ 9♣] Pair, Kings, kickers Ten, Nine, Eight [K♣ K♦ T♣ 9♣ 8♦] [5♠ 4♠]
Result:   Player 5 wins with Two Pair, Aces over Sixes, kicker Eight [A♣ A♦ 6♦ 6♠ 8♠]
------ Stud 4 ------
Player 1: [6♠ K♥ A♣ 8♣ 2♠ 5♦ A♥] Pair, Aces, kickers King, Eight, Six [A♣ A♥ K♥ 8♣ 6♠] [5♦ 2♠]
Player 2: [Q♥ 4♥ J♣ 5♥ 2♦ 7♣ 3♠] Nothing, Queen-high, kickers Jack, Seven, Five, Four [Q♥ J♣ 7♣ 5♥ 4♥] [3♠ 2♦]
Player 3: [2♣ 6♥ 5♣ Q♠ 6♦ 9♥ 3♣] Pair, Sixes, kickers Queen, Nine, Five [6♦ 6♥ Q♠ 9♥ 5♣] [3♣ 2♣]
Player 4: [9♠ J♥ K♠ J♠ 6♣ K♦ T♠] Two Pair, Kings over Jacks, kicker Ten [K♦ K♠ J♥ J♠ T♠] [9♠ 6♣]
Player 5: [3♦ 4♦ K♣ 8♦ 8♥ 9♣ T♥] Pair, Eights, kickers King, Ten, Nine [8♦ 8♥ K♣ T♥ 9♣] [4♦ 3♦]
Player 6: [T♣ Q♦ A♠ 7♥ Q♣ 7♦ 2♥] Two Pair, Queens over Sevens, kicker Ace [Q♣ Q♦ 7♦ 7♥ A♠] [T♣ 2♥]
Result:   Player 4 wins with Two Pair, Kings over Jacks, kicker Ten [K♦ K♠ J♥ J♠ T♠]
------ Stud 5 ------
Player 1: [3♦ 4♦ 5♦ J♣ 4♥ K♥ 8♣] Pair, Fours, kickers King, Jack, Eight [4♦ 4♥ K♥ J♣ 8♣] [5♦ 3♦]
Player 2: [T♥ J♠ K♠ 2♣ 4♣ 5♠ 2♦] Pair, Twos, kickers King, Jack, Ten [2♣ 2♦ K♠ J♠ T♥] [5♠ 4♣]
Player 3: [A♣ 9♠ T♠ 3♠ K♣ 8♦ A♥] Pair, Aces, kickers King, Ten, Nine [A♣ A♥ K♣ T♠ 9♠] [8♦ 3♠]
Player 4: [7♦ 3♣ 8♠ 7♣ 6♦ 6♥ 6♣] Full House, Sixes full of Sevens [6♣ 6♦ 6♥ 7♣ 7♦] [8♠ 3♣]
Player 5: [5♣ Q♠ J♥ 2♠ A♠ 8♥ 4♠] Nothing, Ace-high, kickers Queen, Jack, Eight, Five [A♠ Q♠ J♥ 8♥ 5♣] [4♠ 2♠]
Player 6: [6♠ 7♠ 7♥ 2♥ 9♦ K♦ T♦] Pair, Sevens, kickers King, Ten, Nine [7♥ 7♠ K♦ T♦ 9♦] [6♠ 2♥]
Result:   Player 4 wins with Full House, Sixes full of Sevens [6♣ 6♦ 6♥ 7♣ 7♦]
Example (StudHiLo)
package main

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

	"github.com/cardrank/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, 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())
			fmt.Printf("  Lo: %s %b %b\n", hands[j].LowDescription(), hands[j].LowBest(), hands[j].LowUnused())
		}
		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♥ J♣ A♥ Q♠ 6♣ 5♥ Q♦]
  Hi: Pair, Queens, kickers Ace, King, Jack [Q♦ Q♠ A♥ K♥ J♣] [6♣ 5♥]
  Lo: None [] []
Player 2: [7♣ 4♣ 5♠ 2♠ 3♥ 4♥ 7♥]
  Hi: Two Pair, Sevens over Fours, kicker Five [7♣ 7♥ 4♣ 4♥ 5♠] [3♥ 2♠]
  Lo: Seven, Five, Four, Three, Two-low [7♣ 5♠ 4♣ 3♥ 2♠] [4♥ 7♥]
Result (Hi): Player 2 wins with Two Pair, Sevens over Fours, kicker Five [7♣ 7♥ 4♣ 4♥ 5♠]
Result (Lo): Player 2 wins with Seven, Five, Four, Three, Two-low [7♣ 5♠ 4♣ 3♥ 2♠]
------ StudHiLo 2 ------
Player 1: [3♠ 3♦ T♠ Q♠ T♥ 9♠ K♥]
  Hi: Two Pair, Tens over Threes, kicker King [T♥ T♠ 3♦ 3♠ K♥] [Q♠ 9♠]
  Lo: None [] []
Player 2: [6♦ Q♣ 8♥ 6♣ 3♥ T♣ 7♥]
  Hi: Pair, Sixes, kickers Queen, Ten, Eight [6♣ 6♦ Q♣ T♣ 8♥] [7♥ 3♥]
  Lo: None [] []
Player 3: [Q♦ K♠ 8♣ A♥ 7♣ 9♣ 2♣]
  Hi: Nothing, Ace-high, kickers King, Queen, Nine, Eight [A♥ K♠ Q♦ 9♣ 8♣] [7♣ 2♣]
  Lo: None [] []
Player 4: [K♦ T♦ 8♦ 4♥ 3♣ J♠ 2♦]
  Hi: Nothing, King-high, kickers Jack, Ten, Eight, Four [K♦ J♠ T♦ 8♦ 4♥] [3♣ 2♦]
  Lo: None [] []
Player 5: [J♦ 2♥ Q♥ 6♠ 5♦ 7♠ A♦]
  Hi: Nothing, Ace-high, kickers Queen, Jack, Seven, Six [A♦ Q♥ J♦ 7♠ 6♠] [5♦ 2♥]
  Lo: Seven, Six, Five, Two, Ace-low [7♠ 6♠ 5♦ 2♥ A♦] [J♦ Q♥]
Result (Hi): Player 1 wins with Two Pair, Tens over Threes, kicker King [T♥ T♠ 3♦ 3♠ K♥]
Result (Lo): Player 5 wins with Seven, Six, Five, Two, Ace-low [7♠ 6♠ 5♦ 2♥ A♦]
------ StudHiLo 3 ------
Player 1: [K♠ Q♠ 4♣ J♦ 7♥ 7♣ J♥]
  Hi: Two Pair, Jacks over Sevens, kicker King [J♦ J♥ 7♣ 7♥ K♠] [Q♠ 4♣]
  Lo: None [] []
Player 2: [J♠ 3♣ 8♥ 2♠ J♣ Q♣ 7♦]
  Hi: Pair, Jacks, kickers Queen, Eight, Seven [J♣ J♠ Q♣ 8♥ 7♦] [3♣ 2♠]
  Lo: None [] []
Player 3: [3♠ T♠ 2♣ Q♦ T♥ K♥ 3♦]
  Hi: Two Pair, Tens over Threes, kicker King [T♥ T♠ 3♦ 3♠ K♥] [Q♦ 2♣]
  Lo: None [] []
Player 4: [5♣ 5♥ T♦ 2♦ 4♥ 9♦ 2♥]
  Hi: Two Pair, Fives over Twos, kicker Ten [5♣ 5♥ 2♦ 2♥ T♦] [9♦ 4♥]
  Lo: None [] []
Player 5: [7♠ 3♥ 6♠ A♣ 8♠ 6♦ A♦]
  Hi: Two Pair, Aces over Sixes, kicker Eight [A♣ A♦ 6♦ 6♠ 8♠] [7♠ 3♥]
  Lo: Eight, Seven, Six, Three, Ace-low [8♠ 7♠ 6♠ 3♥ A♣] [6♦ A♦]
Player 6: [4♠ 8♦ K♦ T♣ K♣ 5♠ 9♣]
  Hi: Pair, Kings, kickers Ten, Nine, Eight [K♣ K♦ T♣ 9♣ 8♦] [5♠ 4♠]
  Lo: None [] []
Result (Hi): Player 5 wins with Two Pair, Aces over Sixes, kicker Eight [A♣ A♦ 6♦ 6♠ 8♠]
Result (Lo): Player 5 wins with Eight, Seven, Six, Three, Ace-low [8♠ 7♠ 6♠ 3♥ A♣]
------ StudHiLo 4 ------
Player 1: [6♠ K♥ A♣ 8♣ 2♠ 5♦ A♥]
  Hi: Pair, Aces, kickers King, Eight, Six [A♣ A♥ K♥ 8♣ 6♠] [5♦ 2♠]
  Lo: Eight, Six, Five, Two, Ace-low [8♣ 6♠ 5♦ 2♠ A♣] [K♥ A♥]
Player 2: [Q♥ 4♥ J♣ 5♥ 2♦ 7♣ 3♠]
  Hi: Nothing, Queen-high, kickers Jack, Seven, Five, Four [Q♥ J♣ 7♣ 5♥ 4♥] [3♠ 2♦]
  Lo: Seven, Five, Four, Three, Two-low [7♣ 5♥ 4♥ 3♠ 2♦] [Q♥ J♣]
Player 3: [2♣ 6♥ 5♣ Q♠ 6♦ 9♥ 3♣]
  Hi: Pair, Sixes, kickers Queen, Nine, Five [6♦ 6♥ Q♠ 9♥ 5♣] [3♣ 2♣]
  Lo: None [] []
Player 4: [9♠ J♥ K♠ J♠ 6♣ K♦ T♠]
  Hi: Two Pair, Kings over Jacks, kicker Ten [K♦ K♠ J♥ J♠ T♠] [9♠ 6♣]
  Lo: None [] []
Player 5: [3♦ 4♦ K♣ 8♦ 8♥ 9♣ T♥]
  Hi: Pair, Eights, kickers King, Ten, Nine [8♦ 8♥ K♣ T♥ 9♣] [4♦ 3♦]
  Lo: None [] []
Player 6: [T♣ Q♦ A♠ 7♥ Q♣ 7♦ 2♥]
  Hi: Two Pair, Queens over Sevens, kicker Ace [Q♣ Q♦ 7♦ 7♥ A♠] [T♣ 2♥]
  Lo: None [] []
Result (Hi): Player 4 wins with Two Pair, Kings over Jacks, kicker Ten [K♦ K♠ J♥ J♠ T♠]
Result (Lo): Player 2 wins with Seven, Five, Four, Three, Two-low [7♣ 5♥ 4♥ 3♠ 2♦]
------ StudHiLo 5 ------
Player 1: [3♦ 4♦ 5♦ J♣ 4♥ K♥ 8♣]
  Hi: Pair, Fours, kickers King, Jack, Eight [4♦ 4♥ K♥ J♣ 8♣] [5♦ 3♦]
  Lo: None [] []
Player 2: [T♥ J♠ K♠ 2♣ 4♣ 5♠ 2♦]
  Hi: Pair, Twos, kickers King, Jack, Ten [2♣ 2♦ K♠ J♠ T♥] [5♠ 4♣]
  Lo: None [] []
Player 3: [A♣ 9♠ T♠ 3♠ K♣ 8♦ A♥]
  Hi: Pair, Aces, kickers King, Ten, Nine [A♣ A♥ K♣ T♠ 9♠] [8♦ 3♠]
  Lo: None [] []
Player 4: [7♦ 3♣ 8♠ 7♣ 6♦ 6♥ 6♣]
  Hi: Full House, Sixes full of Sevens [6♣ 6♦ 6♥ 7♣ 7♦] [8♠ 3♣]
  Lo: None [] []
Player 5: [5♣ Q♠ J♥ 2♠ A♠ 8♥ 4♠]
  Hi: Nothing, Ace-high, kickers Queen, Jack, Eight, Five [A♠ Q♠ J♥ 8♥ 5♣] [4♠ 2♠]
  Lo: Eight, Five, Four, Two, Ace-low [8♥ 5♣ 4♠ 2♠ A♠] [Q♠ J♥]
Player 6: [6♠ 7♠ 7♥ 2♥ 9♦ K♦ T♦]
  Hi: Pair, Sevens, kickers King, Ten, Nine [7♥ 7♠ K♦ T♦ 9♦] [6♠ 2♥]
  Lo: None [] []
Result (Hi): Player 4 wins with Full House, Sixes full of Sevens [6♣ 6♦ 6♥ 7♣ 7♦]
Result (Lo): Player 5 wins with Eight, Five, Four, Two, Ace-low [8♥ 5♣ 4♠ 2♠ 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 InvalidCard = Card(^uint32(0))

InvalidCard is an invalid card.

View Source
const InvalidRank = Rank(^uint8(0))

InvalidRank is an invalid rank.

View Source
const InvalidSuit = Suit(^uint8(0))

InvalidSuit

Variables

View Source
var (
	// DefaultRank is the default hand rank func.
	DefaultRank HandRankFunc
	// DefaultCactus is the default Cactus Kev implementation.
	DefaultCactus RankFunc
)

Functions

func Cactus added in v0.8.0

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

Cactus is a Cactus Kev hand rank func that generates the lookup maps on the fly.

See: https://archive.is/G6GZg

func CactusFast added in v0.8.0

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

CactusFast is a fast Cactus Kev hand rank func, implementing Paul Senzee's perfect hash lookup.

See: http://senzee.blogspot.com/2006/06/some-perfect-hash.html

func HoldemBlinds added in v0.8.0

func HoldemBlinds() []string

HoldemBlinds returns the Holdem blind names.

func Init

func Init() error

Init inits the package level default variables. Must be manually called prior to using this package when built with the `noinit` build tag.

func LowOrder

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 Order

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(rank Rank, suit Suit) rune

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

func PlayingCardRune

func PlayingCardRune(rank Rank, suit Suit) rune

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

func RankEightOrBetter added in v0.8.0

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

RankEightOrBetter is a 8-or-better low hand rank func. Aces are low, straights and flushes do not count. Any card with rank 8 or higher will cause

func RankLowAceFive added in v0.8.0

func RankLowAceFive(mask uint16, c0, c1, c2, c3, c4 Card) uint16

RankLowAceFive is a Ace-to-Five low hand rank func.

func RankRazz added in v0.8.0

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

RankRazz is a Razz (Ace-to-Five) low hand rank func. Aces are low, straights and flushes do not count.

When there is a pair (or higher) of matching ranks, will be the inverted value of the regular hand rank.

func RegisterDefaultTypes added in v0.8.0

func RegisterDefaultTypes() error

RegisterDefaultTypes registers default types.

func RegisterType added in v0.8.0

func RegisterType(id string, typ Type, name string, opts ...TypeOption) error

RegisterType registers a type.

func ShortComp added in v0.8.0

func ShortComp(a, b *Hand) int

ShortComp is the compare func for Short decks.

func StudBlinds added in v0.8.0

func StudBlinds() []string

StudBlinds returns the Stud blind names.

func WinVerb added in v0.8.0

func WinVerb(n int, scoop bool) string

WinVerb returns the win verb.

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"

	"github.com/cardrank/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 FromIndex

func FromIndex(i int) Card

FromIndex creates a card from a numerical index (0-51).

func FromRune

func FromRune(r rune) Card

FromRune creates a card from a unicode playing card rune.

Example
package main

import (
	"fmt"

	"github.com/cardrank/cardrank"
)

func main() {
	c := cardrank.FromRune('🂡')
	fmt.Printf("%b\n", c)
}
Output:

A♠

func FromString

func FromString(s string) Card

FromString creates a card from a string.

Example
package main

import (
	"fmt"

	"github.com/cardrank/cardrank"
)

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

Ace of Hearts (A♥)

func Must

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

Must creates a Card slice from v.

See Parse for overview of accepted string representations of cards.

Example
package main

import (
	"fmt"

	"github.com/cardrank/cardrank"
)

func main() {
	hand := cardrank.Must("Ah K♠ 🃍 J♤ 10h")
	fmt.Printf("%b", hand)
}
Output:

[A♥ K♠ Q♦ J♠ T♥]

func New

func New(rank Rank, suit Suit) Card

New creates a card for the specified rank and suit.

func Parse

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

Parse parses strings of Card representations from v. Ignores whitespace between cards and case. Combines all parsed representations into a single Card slice.

Cards can described using common text strings (such as "Ah", "ah", "aH", or "AH"), or having a white or black unicode pip for the suit (such as "J♤" or "K♠"), or single unicode playing card runes (such as "🃆" or "🂣").

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 UnshuffledRoyal

func UnshuffledRoyal() []Card

UnshuffledRoyal generates an unshuffled set of royal cards (10+).

func UnshuffledShort

func UnshuffledShort() []Card

UnshuffledShort generates an unshuffled set of short cards (6+).

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) Index

func (c Card) Index() int

Index returns the index of the card.

func (Card) MarshalText

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

MarshalText satisfies the encoding.TextMarshaler interface.

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 CardFormatter added in v0.8.0

type CardFormatter []Card

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

func (CardFormatter) Format added in v0.8.0

func (v CardFormatter) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

type Dealer added in v0.8.0

type Dealer struct {
	TypeDesc
	// contains filtered or unexported fields
}

Dealer is a deck and street iterator.

func NewDealer added in v0.8.0

func NewDealer(desc TypeDesc, shuffler Shuffler, n int) *Dealer

NewDealer creates a new dealer.

func NewShuffledDealer added in v0.8.0

func NewShuffledDealer(desc TypeDesc, d *Deck) *Dealer

NewShuffledDealer creates a new dealer for an already shuffled deck.

func (*Dealer) Board added in v0.8.0

func (d *Dealer) Board() int

Board returns the current street board.

func (*Dealer) Deal added in v0.8.0

func (d *Dealer) Deal(pockets [][]Card, board []Card, hands int) ([][]Card, []Card)

Deal deals cards for the street.

func (*Dealer) DealAll added in v0.8.0

func (d *Dealer) DealAll(hands int) ([][]Card, []Card)

DealAll deals all pockets, board for the hands. Resets the dealer and the deck.

func (*Dealer) DealBoard added in v0.8.0

func (d *Dealer) DealBoard(board []Card, discard bool) []Card

DealBoard deals and appends the board, returning the appended slice.

func (*Dealer) DealPockets added in v0.8.0

func (d *Dealer) DealPockets(pockets [][]Card, hands int, discard bool) [][]Card

DealPockets deals and appends pockets, returning the appended slice.

func (*Dealer) Format added in v0.8.0

func (d *Dealer) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

func (*Dealer) Next added in v0.8.0

func (d *Dealer) Next() bool

Next returns true when there are more betting streets defined.

func (*Dealer) Pocket added in v0.8.0

func (d *Dealer) Pocket() int

Pocket returns the current street pocket.

func (*Dealer) Reset added in v0.8.0

func (d *Dealer) Reset()

Reset resets the iterator to i.

func (*Dealer) Street added in v0.8.0

func (d *Dealer) Street() StreetDesc

Street returns the current street.

type Deck

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

Deck is a set of playing cards.

func NewDeck

func NewDeck() *Deck

NewDeck creates a new unshuffled deck of cards.

func NewRoyalDeck

func NewRoyalDeck() *Deck

NewRoyalDeck creates a new unshuffled royal deck (10+).

func NewShoeDeck

func NewShoeDeck(n int) *Deck

NewShoeDeck creates a new unshuffled deck "shoe" composed of n decks of unshuffled cards.

func NewShortDeck

func NewShortDeck() *Deck

NewShortDeck creates a new unshuffled short deck (6+).

func (*Deck) Badugi

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(discard int, counts ...int) []Card

Board draws board cards by discarding discard cards, and drawing count cards each for each count 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) DealFor added in v0.8.0

func (d *Deck) DealFor(typ Type, hands int) ([][]Card, []Card)

DealFor deals hands for the type.

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"

	"github.com/cardrank/cardrank"
)

func main() {
	d := cardrank.NewDeck()
	// note: use a real random source
	rnd := rand.New(rand.NewSource(52))
	d.Shuffle(rnd)
	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) MultiBoard

func (d *Deck) MultiBoard(n int, discard int, counts ...int) [][]Card

MultiBoard draws n boards of cards, discarding cards, and drawing count cards for each count in counts.

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) Remaining

func (d *Deck) Remaining() int

Remaining returns the number of remaining cards in the deck.

func (*Deck) Reset added in v0.8.0

func (d *Deck) Reset()

Reset resets 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(shuffler Shuffler)

Shuffle shuffles the deck's cards using the provided shuffler.

func (*Deck) ShuffleN

func (d *Deck) ShuffleN(shuffler Shuffler, n int)

ShuffleN shuffles the deck's cards, n times, using the provided shuffler.

func (*Deck) Stud

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 (
	// ErrInvalidId is the invalid id error.
	ErrInvalidId Error = "invalid id"
	// ErrMismatchedIdAndType is the mismatched id and type error.
	ErrMismatchedIdAndType Error = "mismatched id and type"
	// ErrInvalidCard is the invalid card error.
	ErrInvalidCard Error = "invalid card"
	// ErrInvalidType is the invalid type error.
	ErrInvalidType Error = "invalid type"
)

Error values.

func (Error) Error

func (err Error) Error() string

Error satisfies the error interface.

type EvalFunc added in v0.8.0

type EvalFunc func(*Hand)

EvalFunc is a hand rank eval func.

func NewBadugiEval added in v0.8.0

func NewBadugiEval() EvalFunc

NewBadugiEval creates a Badugi hand rank eval func.

func NewHoldemEval added in v0.8.0

func NewHoldemEval(f HandRankFunc, straightHigh Rank) EvalFunc

NewHoldemEval creates a Holdem hand rank eval func.

func NewLowEval added in v0.8.0

func NewLowEval(f RankFunc, loMax HandRank) EvalFunc

NewLowEval creates a low hand rank eval func, using f to determine the best low hand of a 7 card hand.

func NewOmahaEval added in v0.8.0

func NewOmahaEval(loMax HandRank) EvalFunc

NewOmahaEval creates a Omaha hand rank eval func.

func NewOmahaFiveEval added in v0.8.0

func NewOmahaFiveEval(loMax HandRank) EvalFunc

NewOmahaFiveEval creates a new Omaha5 hand rank eval func.

func NewOmahaSixEval added in v0.8.0

func NewOmahaSixEval(loMax HandRank) EvalFunc

NewOmahaSixEval creates a new Omaha6 hand rank eval func.

func NewRazzEval added in v0.8.0

func NewRazzEval() EvalFunc

NewRazzEval creates a Razz hand rank eval func.

func NewShortEval added in v0.8.0

func NewShortEval() EvalFunc

NewShortEval creates a Holdem 6+ hand rank eval func.

func NewStudEval added in v0.8.0

func NewStudEval(loMax HandRank) EvalFunc

NewStudEval creates a Stud hand rank eval func.

type Hand

type Hand struct {
	Type     Type
	Pocket   []Card
	Board    []Card
	HiRank   HandRank
	HiBest   []Card
	HiUnused []Card
	LoRank   HandRank
	LoBest   []Card
	LoUnused []Card
}

Hand contains hand eval info.

func NewHand

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

NewHand creates an eval for the type, pocket, and board.

Example
package main

import (
	"fmt"
	"math/rand"

	"github.com/cardrank/cardrank"
)

func main() {
	d := cardrank.NewDeck()
	// note: use a real random source
	rnd := rand.New(rand.NewSource(6265))
	d.Shuffle(rnd)
	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 NewUnevaluatedHand added in v0.8.0

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

NewUnevaluatedHand

func (*Hand) Best

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

Best returns the hand's best-five cards.

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) Hand added in v0.8.0

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

Hand returns the combined pocket, board.

func (*Hand) Init added in v0.8.0

func (h *Hand) Init(n, m int, loMax HandRank)

Init inits best, unused.

func (*Hand) LowBest

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

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

func (*Hand) LowCompare

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

LowCompare compares the low hand ranks.

func (*Hand) LowDescription

func (h *Hand) LowDescription() string

LowDescription describes the hands best-five low cards.

func (*Hand) LowRank

func (h *Hand) LowRank() HandRank

LowRank returns the hand's low rank.

func (*Hand) LowUnused

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

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

func (*Hand) LowValid

func (h *Hand) LowValid() bool

LowValid returns true if is a valid low hand.

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 HandCompareFunc added in v0.8.0

type HandCompareFunc func(*Hand, *Hand) int

HandCompareFunc is a hand rank eval compare func.

func NewHiCompare added in v0.8.0

func NewHiCompare() HandCompareFunc

NewHiCompare creates a hi eval compare func.

func NewLoCompare added in v0.8.0

func NewLoCompare(loMax HandRank) HandCompareFunc

NewLoCompare creates a lo eval compare func.

type HandRank

type HandRank uint16

HandRank is a poker hand rank.

Ranks are ordered low-to-high.

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.

See: https://archive.is/G6GZg

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 HandRankFunc added in v0.8.0

type HandRankFunc func([]Card) HandRank

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

func NewHandRank added in v0.8.0

func NewHandRank(f RankFunc) HandRankFunc

NewHandRank creates a hand eval for 5, 6, or 7 cards using f.

func NewHybrid added in v0.8.0

func NewHybrid(f5 RankFunc, f7 HandRankFunc) HandRankFunc

NewHybrid creates a hybrid rank func using f5 for hands with 5 and 6 cards, and f7 for hands with 7 cards.

func NewTwoPlusTwo added in v0.8.0

func NewTwoPlusTwo() HandRankFunc

NewTwoPlusTwo creates a new two plus hand rank eval func.

The TwoPlusTwo eval is a version of the 2+2 poker forum hand rank evaluator. Uses the embedded twoplustwo*.dat files to provide extremely fast 7 card hand lookup. Uses Cactus Kev values.

The lookup table is contained in the 'twoplustwo*.dat' files, and were broken up from a single file to get around GitHub's size limitations. Files were generated with 'gen.go', which is a pure-Go implementation of the code generator available at: https://github.com/tangentforks/TwoPlusTwoHandEvaluator

When recombined, the lookup table has the same hash as the original table generated using the C code.

type ParseError added in v0.7.1

type ParseError struct {
	S   string
	N   int
	I   int
	Err error
}

ParseError is a parse error.

func (*ParseError) Error added in v0.7.1

func (err *ParseError) Error() string

Error satisfies the error interface.

func (*ParseError) Unwrap added in v0.7.1

func (err *ParseError) Unwrap() error

Unwrap satisfies the errors.Unwrap 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

RankFromRune returns the card rank for the rune.

func (Rank) Byte

func (rank Rank) Byte() byte

Byte returns the byte representation for the card rank.

func (Rank) Index

func (rank Rank) Index() int

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

func (Rank) Name

func (rank Rank) Name() string

Name returns the name of the card rank.

func (Rank) PluralName

func (rank Rank) PluralName() string

PluralName returns the plural name of the card rank.

func (Rank) String

func (rank Rank) String() string

String satisfies the fmt.Stringer interface.

type RankFunc added in v0.8.0

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

RankFunc ranks a hand of 5 cards.

type Shuffler added in v0.5.0

type Shuffler interface {
	Shuffle(int, func(int, int))
}

Shuffler is an interface for a deck shuffler. Compatible with math/rand.Rand's Shuffle method.

type StreetDesc added in v0.8.0

type StreetDesc struct {
	// Id is the id of the street.
	Id byte
	// Name is the name of the street.
	Name string
	// Pocket is the count of pocket cards to deal.
	Pocket int
	// PocketUp is the count of pocket cards to reveal.
	PocketUp int
	// PocketDiscard is count of cards to discard before dealing pockets.
	PocketDiscard int
	// PocketSwap is maximum count of pocket cards that can be swapped.
	PocketSwap int
	// Board is the count of board cards to deal.
	Board int
	// BoardDiscard is the count of cards to discard before dealing the board.
	BoardDiscard int
}

StreetDesc is a type's street description.

func HoldemStreets added in v0.8.0

func HoldemStreets(pocket, discard, flop, turn, river int) []StreetDesc

HoldemStreets creates Holdem streets for the pre-flop, flop, turn, and river.

func NumberedStreets added in v0.8.0

func NumberedStreets(pockets ...int) []StreetDesc

NumberedStreets returns numbered streets (ante, first, second, ...).

func StudStreets added in v0.8.0

func StudStreets() []StreetDesc

StudStreets creates Stud streets for the ante, third street, fourth street, fifth street, sixth street and river.

type StreetOption added in v0.8.0

type StreetOption func(int, *StreetDesc)

StreetOption is a street option.

func WithStreetPocket added in v0.8.0

func WithStreetPocket(street, pocket int) StreetOption

WithStreetPocket is a street option to set the pocket for a street.

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

SuitFromRune returns the card suit for the rune.

func (Suit) Byte

func (suit Suit) Byte() byte

Byte returns the byte representation for the card suit.

func (Suit) Index

func (suit Suit) Index() int

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

func (Suit) Name

func (suit Suit) Name() string

Name returns the name of the card suit.

func (Suit) PluralName

func (suit Suit) PluralName() string

PluralName returns the plural name of the card suit.

func (Suit) String

func (suit Suit) String() string

String satisfies the fmt.Stringer interface.

func (Suit) UnicodeBlack

func (suit Suit) UnicodeBlack() rune

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

func (Suit) UnicodeWhite

func (suit Suit) UnicodeWhite() rune

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

type Type

type Type uint16

Type is a hand type.

const (
	Holdem         Type = 'H'<<8 | 'h' // Hh
	Short          Type = 'H'<<8 | 's' // Hs
	Royal          Type = 'H'<<8 | 'r' // Hr
	Double         Type = 'H'<<8 | 'd' // Hd
	Showtime       Type = 'H'<<8 | 't' // Ht
	Swap           Type = 'H'<<8 | 'w' // Hw
	Omaha          Type = 'O'<<8 | '4' // O4
	OmahaHiLo      Type = 'O'<<8 | 'l' // Ol
	OmahaDouble    Type = 'O'<<8 | 'd' // Od
	OmahaFive      Type = 'O'<<8 | '5' // O5
	OmahaSix       Type = 'O'<<8 | '6' // O6
	Courchevel     Type = 'O'<<8 | 'c' // Oc
	CourchevelHiLo Type = 'O'<<8 | 'e' // Oe
	Fusion         Type = 'O'<<8 | 'f' // Of
	Stud           Type = 'S'<<8 | 'h' // Sh
	StudHiLo       Type = 'S'<<8 | 'l' // Sl
	Razz           Type = 'R'<<8 | 'a' // Ra
	Badugi         Type = 'B'<<8 | 'a' // Ba
)

Hand types.

func ToType added in v0.8.0

func ToType(id string) Type

ToType converts an id to a type.

func Types added in v0.8.0

func Types() []Type

Types returns the registered types.

func (Type) Blinds added in v0.8.0

func (typ Type) Blinds() []string

Blinds returns the type's blind names.

func (Type) Deal

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

Deal creates a new deck for the type, shuffling it once, returning the pockets and board for the number of hands specified.

Use DealShuffle when needing to shuffle the deck more than once.

func (Type) DealShuffle

func (typ Type) DealShuffle(shuffler Shuffler, count, hands int) ([][]Card, []Card)

DealShuffle creates a new deck for the type and shuffles the deck count number of times, returning the pockets and board for the number of hands specified.

func (Type) Dealer added in v0.8.0

func (typ Type) Dealer(shuffler Shuffler, n int) *Dealer

Dealer creates a new dealer for the type.

func (Type) Deck

func (typ Type) Deck() *Deck

NewDeck returns a new deck for the type.

func (Type) Desc added in v0.8.0

func (typ Type) Desc() TypeDesc

Desc returns the type description.

func (Type) Double added in v0.8.0

func (typ Type) Double() bool

Double returns true when the type has a double board.

func (Type) Eval added in v0.8.0

func (typ Type) Eval(h *Hand)

Eval evaluates the hand.

func (Type) Format added in v0.8.0

func (typ Type) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

func (Type) HiCompare added in v0.8.0

func (typ Type) HiCompare() HandCompareFunc

HiCompare returns the type's hi compare func.

func (Type) LoCompare added in v0.8.0

func (typ Type) LoCompare() HandCompareFunc

LoCompare returns the type's lo compare func.

func (Type) Low

func (typ Type) Low() bool

Low returns true when the type has a low board.

func (Type) MarshalText

func (typ Type) MarshalText() ([]byte, error)

MarshalText satisfies the encoding.TextMarshaler interface.

func (Type) Max added in v0.8.0

func (typ Type) Max() int

Max returns the type max players.

func (Type) Name added in v0.8.0

func (typ Type) Name() string

Name returns the type name.

func (Type) RankHand

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

RankHand creates a new hand for the pocket, board.

func (Type) RankHands

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

RankHands creates a new hand for the provided pockets and board.

func (Type) Show added in v0.8.0

func (typ Type) Show() bool

Show returns true when the type has a show board.

func (Type) String

func (typ Type) String() string

String satisfies the fmt.Stringer interface.

func (*Type) UnmarshalText

func (typ *Type) UnmarshalText(buf []byte) error

UnmarshalText satisfies the encoding.TextUnmarshaler interface.

type TypeDesc added in v0.8.0

type TypeDesc struct {
	// Num is the registered number.
	Num int
	// Type is the type.
	Type Type
	// Name is the type name.
	Name string
	// Max is the max number of players.
	Max int
	// Low is true when type has low rank.
	Low bool
	// Double is true when there are two boards.
	Double bool
	// Show is true when folded cards are shown.
	Show bool
	// Blinds are the blind names.
	Blinds []string
	// Streets are the betting streets.
	Streets []StreetDesc
	// Deck is the deck func.
	Deck func() *Deck
	// Eval is the eval func.
	Eval EvalFunc
	// HiCompare is the hi compare func.
	HiCompare HandCompareFunc
	// LoCompare is the lo compare func.
	LoCompare HandCompareFunc
}

TypeDesc is a type description.

func (*TypeDesc) Apply added in v0.8.0

func (desc *TypeDesc) Apply(opts ...StreetOption)

Apply applies street options.

type TypeOption added in v0.8.0

type TypeOption func(*TypeDesc)

TypeOption is a type description option.

func WithBadugi added in v0.8.0

func WithBadugi(opts ...StreetOption) TypeOption

WithBadugi is a type description option to set standard Badugi definitions.

4 cards, low evaluation of separate suits All 4 face down pre-flop 3 rounds of player discards (up to 4)

func WithCourchevel added in v0.8.0

func WithCourchevel(hiLo bool, opts ...StreetOption) TypeOption

WithCourchevel is a type description option to set standard Courchevel definitions.

func WithDouble added in v0.8.0

func WithDouble(opts ...StreetOption) TypeOption

WithDouble is a type description option to set Double definitions.

func WithFusion added in v0.8.0

func WithFusion(hiLo bool, opts ...StreetOption) TypeOption

WithFusion is a type description option to set standard Fusion definitions.

func WithHoldem added in v0.8.0

func WithHoldem(opts ...StreetOption) TypeOption

WithHoldem is a type description option to set Holdem definitions.

func WithOmaha added in v0.8.0

func WithOmaha(hiLo bool, opts ...StreetOption) TypeOption

WithOmaha is a type description option to set standard Omaha definitions.

func WithOmahaDouble added in v0.8.0

func WithOmahaDouble(opts ...StreetOption) TypeOption

WithOmahaDouble is a type description option to set standard OmahaDouble definitions.

func WithOmahaFive added in v0.8.0

func WithOmahaFive(hiLo bool, opts ...StreetOption) TypeOption

WithOmahaFive is a type description option to set standard OmahaFive definitions.

func WithOmahaSix added in v0.8.0

func WithOmahaSix(hiLo bool, opts ...StreetOption) TypeOption

WithOmahaSix is a type description option to set standard OmahaSix definitions.

func WithRazz added in v0.8.0

func WithRazz(opts ...StreetOption) TypeOption

WithRazz is a type description option to set standard Razz definitions.

Same as Stud, but with a Ace-to-Five low card ranking.

func WithRoyal added in v0.8.0

func WithRoyal(opts ...StreetOption) TypeOption

WithRoyal is a type description option to set Royal definitions.

func WithShort added in v0.8.0

func WithShort(opts ...StreetOption) TypeOption

WithShort is a type description option to set Holdem 6+ definitions.

func WithShowtime added in v0.8.0

func WithShowtime(opts ...StreetOption) TypeOption

WithShowtime is a type description option to set Showtime definitions.

func WithStud added in v0.8.0

func WithStud(hiLo bool, opts ...StreetOption) TypeOption

WithStud is a type description option to set standard Stud definitions.

type Win added in v0.8.0

type Win struct {
	Hi      []int
	HiPivot int
	Lo      []int
	LoPivot int
	Low     bool
}

Win describes a win.

func NewWin added in v0.8.0

func NewWin(h1, h2 []*Hand, low bool) Win

NewWin creates a new win.

func (Win) Describe added in v0.8.0

func (win Win) Describe(f func(int, int) string) string

Describe returns a description.

func (Win) Format added in v0.8.0

func (win Win) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

func (Win) Join added in v0.8.0

func (win Win) Join(f func(int, int) string, sep string) string

Join joins strings.

func (Win) LowDescribe added in v0.8.0

func (win Win) LowDescribe(f func(int, int) string) string

LowDescribe returns a low description.

func (Win) LowJoin added in v0.8.0

func (win Win) LowJoin(f func(int, int) string, sep string) string

LowJoin joins strings.

func (Win) LowVerb added in v0.8.0

func (win Win) LowVerb() string

LowVerb returns the win verb.

func (Win) Scoop added in v0.8.0

func (win Win) Scoop() bool

Scoop returns true when a pot is scooped.

func (Win) Verb added in v0.8.0

func (win Win) Verb() string

Verb returns the win verb.

Directories

Path Synopsis
_example

Jump to

Keyboard shortcuts

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