cardrank

package module
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2024 License: MIT Imports: 13 Imported by: 0

README

About

Package cardrank is a library of types, utilities, and interfaces for working with playing cards, card decks, evaluating poker ranks, managing deals and run outs for different game types.

Tests Go Report Card Reference Releases

Overview

The cardrank package contains types for working with Card's, Suit's, Rank's, Deck's, evaluating poker ranks, and managing deals and run outs.

In most cases, using the high-level Dealer with any registered Type should be sufficient for most purposes. An in-depth example is provided in the package documentation.

A Type wraps a type description defining a type's deal streets, deck, eval, Hi/Lo description and other meta-data needed for dealing streets and managing run outs.

Evaluation and ranking of the types is accomplished through pure Go implementations of well-known poker rank evaluation algorithms. Evaluation of cards can be compared and ordered to determine winner(s).

Supported Types

Supports evaluating and ranking the following Type's:

Holdem Variants Omaha Variants Hybrid Variants Draw Variants Other
Holdem Omaha Dallas Video Soko
Split OmahaHiLo Houston Draw SokoHiLo
Short OmahaDouble Fusion DrawHiLo Lowball
Manila OmahaFive FusionHiLo Stud LowballTriple
Spanish OmahaSix StudHiLo Razz
Royal Courchevel StudFive Badugi
Double CourchevelHiLo
Showtime
Swap
River

See the package's Type documentation for an overview of the above.

Using

To use within a Go package:

go get github.com/cardrank/cardrank

See package level Go package documentation for in-depth overviews of APIs.

Quickstart

Various examples are available in the Go package documentation showing use of various types, utilities, and interfaces.

Additional examples for a Dealer and the Holdem and OmahaHiLo types are included in the example directory:

  • dealer - shows use of the Dealer, to handle dealing cards, handling multiple run outs, and determining winners using any Type's
  • holdem - shows using types and utilities to deal Holdem
  • omahahilo - shows using types and utilities to OmahaHiLo, demonstrating splitting Hi and Lo wins
Eval Ranking

EvalRank's are determined using a registered EvalFunc associated with the Type. EvalRank's are always ordered, low to high, and are relative/comparable:

fmt.Printf("%t\n", cardrank.StraightFlush < cardrank.FullHouse)

// Output:
// true

Pocket and board Card's can be passed to a Type's Eval method, which in turn uses the Type's registered EvalFunc and returns an Evaluated value:

pocket, board := cardrank.Must("Ah Kh"), cardrank.Must("Qh Jh Th 2s 3s")
ev := cardrank.Holdem.Eval(pocket, board)
fmt.Printf("%s - %d\n", ev, ev.HiRank)

// Output:
// Straight Flush, Ace-high, Royal [Ah Kh Qh Jh Th] - 1

When evaluating cards, usually the eval is for 5, 6, or 7 cards, but some Type's are capable of evaluating fewer Card's:

pocket := cardrank.Must("2h 3s 4c")
ev := cardrank.Badugi.Eval(pocket, nil)
fmt.Printf("%s\n", ev)

// Output:
// Four, Three, Two-low [4c 3s 2h]

If an invalid number of cards is passed to a Type's EvalFunc, the Eval's HiRank and LoRank values will be set to Invalid.

Eval's can be used to compare different hands of Card's in order to determine a winner, by comparing the Eval.HiRank or Eval.LoRank values.

Hi/Lo

Different Type's may have both a Hi and Lo EvalRank, such as Double board Holdem, and various *HiLo variants, such as OmahaHiLo.

When a Eval is created, both the Hi and Lo values will be made available in the resulting Eval as the HiRank and LoRank, respectively.

Cactus Kev

For most Type's, the EvalRank is determined by Go implementations of a few well-known Cactus Kev algorithms:

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.

Rank Cactus Func

The package-level RankCactus variable is used for regular poker evaluation, and can be set externally when wanting to build new game types, or trying new algorithms.

Two-Plus-Two

NewTwoPlusTwoEval 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 lookup table can be excluded when using the portable or embedded build tags, with a tradeoff of slightly degraded performance when evaluating 7 cards.

Note: the Two-Plus-Two eval is disabled by default when GOOS=js (ie, WASM) builds, but can be forced included with the forcefat build tag.

Winner Determination

Winner(s) are determined by the lowest possible EvalRank for either the Hi or Lo value for the Type. Two or more hands having a EvalRank of equal value indicate that the hands have equivalent ranks, and have both won.

Eval's can be sorted (low-to-high) by the Eval's HiRank and LoRank member variables. Winner(s) of a hand will be the hands in the lowest position and having equivalent HiRank's or LoRank's.

Comparing Eval Ranks

A Eval can be compared to another Eval using Comp. Comp returns -1, 0, or +1, making it easy to compare or sort hands:

// Compare a and b's Hi:
if a.Comp(b, false) < 0 {
	fmt.Printf("%s is a winner!", a)
}

// Compare a and b's Lo:
if a.Comp(b, true) == 0 {
	fmt.Printf("%s and %s are equal!", a, b)
}

// Sort slice of []*Eval by Hi:
sort.Slice(evs, func(i, j int) bool {
	return evs[i].Comp(evs[j], false) < 0
})

// Sort slice of []*Eval by Lo:
sort.Slice(evs, func(i, j int) bool {
	return evs[i].Comp(evs[j], true) < 0
})

The package level Order func is provided as a high-level way to order Eval slices and to determine winners. See ordering evals below.

Ordering Evals

Order can determine the winner(s) of a hand by ordering the indexes of a []*Eval and returning the list of ordered evals as a []int and an int pivot indicating the position within the returned []int as a cutoff for a win:

// Order by HiRank:
hiOrder, hiPivot := cardrank.Order(evs, false)

For a Type with a lo value:

// Order by LoRank:
loOrder, loPivot := cardrank.Order(evs, true)

A Eval whose index is in position i < pivot is considered to be the winner(s). When ordering by HiRank, there will be 1 or more winner(s) (with exception for Video types), but when ordering by LoRank there may be 0 or more winner(s):

for i := 0; i < hiPivot; i++ {
	fmt.Printf("%s is a Hi winner!", evs[hiOrder[i]])
}

Similarly, for lo winners:

for i := 0; i < loPivot; i++ {
	fmt.Printf("%s is a Lo winner!", evs[loOrder[i]])
}
Build Tags

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

portable

The portable tag disables inclusion of the Two-plus-two lookup tables, 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 RankCactus and to register the default types automatically:

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

Alternatively, the RankCactus can be set manually. After RankCactus has been set, call RegisterDefaultTypes to register built in types:

// Set when using a third-party implementation, or experimenting with new
// Cactus implementations:
cardrank.RankCactus = cardrank.CactusFast

// 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

Documentation

Overview

Package cardrank is a library of types, utilities, and interfaces for working with playing cards, card decks, evaluating poker hand ranks, and managing deals and run outs for different game types.

Example
package main

import (
	"fmt"
	"math/rand"

	"github.com/cardrank/cardrank"
)

func main() {
	for i, game := range []struct {
		seed     int64
		players  int
		change   byte
		runs     int
		inactive []int
		names    []string
	}{
		{566, 2, 't', 3, nil, []string{"Alice", "Bob"}},
		{1039, 5, 'f', 2, []int{0, 3, 4}, []string{"Alice", "Bob", "Carl", "Dave", "Elizabeth"}},
		{2087, 6, 't', 2, []int{0, 5}, []string{"Alice", "Bob", "Carl", "Dave", "Elizabeth", "Frank"}},
		{4022, 6, 'p', 2, []int{0, 1, 4}, []string{"Alice", "Bob", "Carl", "Dave", "Elizabeth", "Fenny"}},
	} {
		// note: use a real random source
		r := rand.New(rand.NewSource(game.seed))
		fmt.Printf("------ FusionHiLo %d ------\n", i+1)
		// setup dealer and display
		d := cardrank.FusionHiLo.Dealer(r, 1, game.players)
		// display deck
		deck := d.Deck.All()
		fmt.Println("Deck:")
		for i := 0; i < len(deck); i += 8 {
			n := i + 8
			if n > len(deck) {
				n = len(deck)
			}
			fmt.Printf("  %v\n", deck[i:n])
		}
		last := -1
		for d.Next() {
			i, run := d.Run()
			if last != i {
				fmt.Printf("Run %d:\n", i)
			}
			last = i
			fmt.Printf("  %s\n", d)
			// display pockets
			if d.HasPocket() {
				for i := 0; i < game.players; i++ {
					fmt.Printf("    %d %s: %v\n", i, game.names[i], run.Pockets[i])
				}
			}
			// display discarded cards
			if v := d.Discarded(); len(v) != 0 {
				fmt.Printf("    Discard: %v\n", v)
			}
			// display board
			if d.HasBoard() {
				fmt.Printf("    Board: %v\n", run.Hi)
				if d.Double {
					fmt.Printf("           %v\n", run.Lo)
				}
			}
			// change runs, deactivate positions
			if d.Id() == game.change && i == 0 {
				if success := d.ChangeRuns(game.runs); !success {
					panic("unable to change runs")
				}
				// deactivate
				if success := d.Deactivate(game.inactive...); !success {
					panic("unable to deactivate positions")
				}
			}
		}
		fmt.Println("Showdown:")
		for d.NextResult() {
			n, res := d.Result()
			fmt.Printf("  Run %d:\n", n)
			for i := 0; i < game.players; i++ {
				if d.Active[i] {
					hi := res.Evals[i].Desc(false)
					fmt.Printf("    %d: %v %v %s\n", i, hi.Best, hi.Unused, hi)
					if d.Low || d.Double {
						lo := res.Evals[i].Desc(true)
						fmt.Printf("       %v %v %s\n", lo.Best, lo.Unused, lo)
					}
				} else {
					fmt.Printf("    %d: inactive\n", i)
				}
			}
			hi, lo := res.Win(game.names...)
			fmt.Printf("    Result: %S\n", hi)
			if lo != nil {
				fmt.Printf("            %S\n", lo)
			}
		}
	}
}
Output:

------ FusionHiLo 1 ------
Deck:
  [4h Qs 5c 4c 5d 8d 8c As]
  [Ks 6h 7s 9s 3h Ac Js 9h]
  [4s 7d 2h 8s 2s Ad Ts Qh]
  [Qc 5h 6s 9d 9c 6c Kd 2d]
  [3s Ah Kh 5s Jd Jc 2c Td]
  [3c Jh 8h 4d Th 7c 7h 3d]
  [6d Tc Kc Qd]
Run 0:
  p: Pre-Flop (p: 2)
    0 Alice: [4h 5c]
    1 Bob: [Qs 4c]
  f: Flop (p: 1, d: 1, b: 3)
    0 Alice: [4h 5c 5d]
    1 Bob: [Qs 4c 8d]
    Discard: [8c]
    Board: [As Ks 6h]
  t: Turn (p: 1, d: 1, b: 1)
    0 Alice: [4h 5c 5d 7s]
    1 Bob: [Qs 4c 8d 9s]
    Discard: [8c 3h]
    Board: [As Ks 6h Ac]
  r: River (d: 1, b: 1)
    Discard: [8c 3h Js]
    Board: [As Ks 6h Ac 9h]
Run 1:
  r: River (d: 1, b: 1)
    Discard: [4s]
    Board: [As Ks 6h Ac 7d]
Run 2:
  r: River (d: 1, b: 1)
    Discard: [2h]
    Board: [As Ks 6h Ac 8s]
Showdown:
  Run 0:
    0: [Ac As 5c 5d Ks] [9h 7s 6h 4h] Two Pair, Aces over Fives, kicker King
       [] [] None
    1: [Ac As 9h 9s Qs] [Ks 8d 6h 4c] Two Pair, Aces over Nines, kicker Queen
       [] [] None
    Result: Bob scoops with Two Pair, Aces over Nines, kicker Queen
  Run 1:
    0: [Ac As 7d 7s 5c] [Ks 6h 5d 4h] Two Pair, Aces over Sevens, kicker Five
       [7d 6h 5c 4h As] [Ac Ks 7s 5d] Seven, Six, Five, Four, Ace-low
    1: [Ac As Ks Qs 9s] [8d 7d 6h 4c] Pair, Aces, kickers King, Queen, Nine
       [8d 7d 6h 4c As] [Ac Ks Qs 9s] Eight, Seven, Six, Four, Ace-low
    Result: Alice wins with Two Pair, Aces over Sevens, kicker Five
            Alice wins with Seven, Six, Five, Four, Ace-low
  Run 2:
    0: [Ac As 5c 5d Ks] [8s 7s 6h 4h] Two Pair, Aces over Fives, kicker King
       [8s 6h 5c 4h As] [Ac Ks 7s 5d] Eight, Six, Five, Four, Ace-low
    1: [As Ks Qs 9s 8s] [Ac 8d 6h 4c] Flush, Ace-high, kickers King, Queen, Nine, Eight
       [] [] None
    Result: Bob wins with Flush, Ace-high, kickers King, Queen, Nine, Eight
            Alice wins with Eight, Six, Five, Four, Ace-low
------ FusionHiLo 2 ------
Deck:
  [2h 5s Ac Ts Kd 5h 6d Th]
  [2s 6s 7c 4h 8c 9h Ah 8s]
  [Kc 9d 5c 5d As 4d 3h 2c]
  [7s 8h 4c 7d 8d Qs 3c 7h]
  [Jc Jh 6c 3s Qd 9c 4s 3d]
  [Ks Ad Qc Td Tc Qh Js 6h]
  [2d 9s Jd Kh]
Run 0:
  p: Pre-Flop (p: 2)
    0 Alice: [2h 5h]
    1 Bob: [5s 6d]
    2 Carl: [Ac Th]
    3 Dave: [Ts 2s]
    4 Elizabeth: [Kd 6s]
  f: Flop (p: 1, d: 1, b: 3)
    0 Alice: [2h 5h 7c]
    1 Bob: [5s 6d 4h]
    2 Carl: [Ac Th 8c]
    3 Dave: [Ts 2s 9h]
    4 Elizabeth: [Kd 6s Ah]
    Discard: [8s]
    Board: [Kc 9d 5c]
  t: Turn (p: 1, d: 1, b: 1)
    0 Alice: [2h 5h 7c 5d]
    1 Bob: [5s 6d 4h As]
    2 Carl: [Ac Th 8c 4d]
    3 Dave: [Ts 2s 9h 3h]
    4 Elizabeth: [Kd 6s Ah 2c]
    Discard: [8s 7s]
    Board: [Kc 9d 5c 8h]
  r: River (d: 1, b: 1)
    Discard: [8s 7s 4c]
    Board: [Kc 9d 5c 8h 7d]
Run 1:
  t: Turn (p: 1, d: 1, b: 1)
    0 Alice: [2h 5h 7c 8d]
    1 Bob: [5s 6d 4h Qs]
    2 Carl: [Ac Th 8c 3c]
    3 Dave: [Ts 2s 9h 7h]
    4 Elizabeth: [Kd 6s Ah Jc]
    Discard: [Jh]
    Board: [Kc 9d 5c 6c]
  r: River (d: 1, b: 1)
    Discard: [Jh 3s]
    Board: [Kc 9d 5c 6c Qd]
Showdown:
  Run 0:
    0: inactive
    1: [9d 8h 7d 6d 5s] [As Kc 5c 4h] Straight, Nine-high
       [8h 7d 5c 4h As] [Kc 9d 6d 5s] Eight, Seven, Five, Four, Ace-low
    2: [8c 8h Ac Kc 9d] [Th 7d 5c 4d] Pair, Eights, kickers Ace, King, Nine
       [8h 7d 5c 4d Ac] [Kc Th 9d 8c] Eight, Seven, Five, Four, Ace-low
    3: inactive
    4: inactive
    Result: Bob wins with Straight, Nine-high
            Bob, Carl split with Eight, Seven, Five, Four, Ace-low
  Run 1:
    0: inactive
    1: [Qd Qs 6c 6d Kc] [9d 5c 5s 4h] Two Pair, Queens over Sixes, kicker King
       [] [] None
    2: [Ac Kc 8c 6c 5c] [Qd Th 9d 3c] Flush, Ace-high, kickers King, Eight, Six, Five
       [] [] None
    3: inactive
    4: inactive
    Result: Carl scoops with Flush, Ace-high, kickers King, Eight, Six, Five
------ FusionHiLo 3 ------
Deck:
  [8h 5d 5c 3h Jc 6h Kd Td]
  [6s As 7c 6c 2c Jd 9h 8c]
  [7s 5s 8d Tc 3s Kc Qh Qd]
  [7d Ks Jh 4s 9s 4h Th Qc]
  [Ah 2d Ts 7h 4c Qs Kh 6d]
  [9d 2s Js 3d 5h 2h Ac Ad]
  [3c 8s 4d 9c]
Run 0:
  p: Pre-Flop (p: 2)
    0 Alice: [8h Kd]
    1 Bob: [5d Td]
    2 Carl: [5c 6s]
    3 Dave: [3h As]
    4 Elizabeth: [Jc 7c]
    5 Frank: [6h 6c]
  f: Flop (p: 1, d: 1, b: 3)
    0 Alice: [8h Kd 2c]
    1 Bob: [5d Td Jd]
    2 Carl: [5c 6s 9h]
    3 Dave: [3h As 8c]
    4 Elizabeth: [Jc 7c 7s]
    5 Frank: [6h 6c 5s]
    Discard: [8d]
    Board: [Tc 3s Kc]
  t: Turn (p: 1, d: 1, b: 1)
    0 Alice: [8h Kd 2c Qh]
    1 Bob: [5d Td Jd Qd]
    2 Carl: [5c 6s 9h 7d]
    3 Dave: [3h As 8c Ks]
    4 Elizabeth: [Jc 7c 7s Jh]
    5 Frank: [6h 6c 5s 4s]
    Discard: [8d 9s]
    Board: [Tc 3s Kc 4h]
  r: River (d: 1, b: 1)
    Discard: [8d 9s Th]
    Board: [Tc 3s Kc 4h Qc]
Run 1:
  r: River (d: 1, b: 1)
    Discard: [Ah]
    Board: [Tc 3s Kc 4h 2d]
Showdown:
  Run 0:
    0: inactive
    1: [Qc Qd Tc Td Kc] [Jd 5d 4h 3s] Two Pair, Queens over Tens, kicker King
       [] [] None
    2: [Kc Qc Tc 9h 7d] [6s 5c 4h 3s] King-high, kickers Queen, Ten, Nine, Seven
       [] [] None
    3: [Kc Ks 3h 3s Qc] [As Tc 8c 4h] Two Pair, Kings over Threes, kicker Queen
       [] [] None
    4: [Kc Qc Jc Tc 7c] [Jh 7s 4h 3s] Flush, King-high, kickers Queen, Jack, Ten, Seven
       [] [] None
    5: inactive
    Result: Elizabeth scoops with Flush, King-high, kickers Queen, Jack, Ten, Seven
  Run 1:
    0: inactive
    1: [Tc Td Kc Qd 4h] [Jd 5d 3s 2d] Pair, Tens, kickers King, Queen, Four
       [] [] None
    2: [6s 5c 4h 3s 2d] [Kc Tc 9h 7d] Straight, Six-high
       [6s 5c 4h 3s 2d] [Kc Tc 9h 7d] Six, Five, Four, Three, Two-low
    3: [Kc Ks 3h 3s Tc] [As 8c 4h 2d] Two Pair, Kings over Threes, kicker Ten
       [8c 4h 3s 2d As] [Kc Ks Tc 3h] Eight, Four, Three, Two, Ace-low
    4: [Jc Jh Kc Tc 4h] [7c 7s 3s 2d] Pair, Jacks, kickers King, Ten, Four
       [] [] None
    5: inactive
    Result: Carl wins with Straight, Six-high
            Carl wins with Six, Five, Four, Three, Two-low
------ FusionHiLo 4 ------
Deck:
  [Qc 4h 2c 7c Kc 5c 9d 5h]
  [3c Tc 9c Qd As 4s 5d Jc]
  [4c Ad 9s 8s Qh 3h Td 7h]
  [7s Ks 6d Kd 7d Jh 2d Js]
  [4d 6h Th Ah Ac Ts 3d 6c]
  [Jd 2s 2h 9h 3s 5s 8d 8c]
  [Qs 8h Kh 6s]
Run 0:
  p: Pre-Flop (p: 2)
    0 Alice: [Qc 9d]
    1 Bob: [4h 5h]
    2 Carl: [2c 3c]
    3 Dave: [7c Tc]
    4 Elizabeth: [Kc 9c]
    5 Fenny: [5c Qd]
  f: Flop (p: 1, d: 1, b: 3)
    0 Alice: [Qc 9d As]
    1 Bob: [4h 5h 4s]
    2 Carl: [2c 3c 5d]
    3 Dave: [7c Tc Jc]
    4 Elizabeth: [Kc 9c 4c]
    5 Fenny: [5c Qd Ad]
    Discard: [9s]
    Board: [8s Qh 3h]
  t: Turn (p: 1, d: 1, b: 1)
    0 Alice: [Qc 9d As Td]
    1 Bob: [4h 5h 4s 7h]
    2 Carl: [2c 3c 5d 7s]
    3 Dave: [7c Tc Jc Ks]
    4 Elizabeth: [Kc 9c 4c 6d]
    5 Fenny: [5c Qd Ad Kd]
    Discard: [9s 7d]
    Board: [8s Qh 3h Jh]
  r: River (d: 1, b: 1)
    Discard: [9s 7d 2d]
    Board: [8s Qh 3h Jh Js]
Run 1:
  f: Flop (p: 1, d: 1, b: 3)
    0 Alice: [Qc 9d 4d]
    1 Bob: [4h 5h 6h]
    2 Carl: [2c 3c Th]
    3 Dave: [7c Tc Ah]
    4 Elizabeth: [Kc 9c Ac]
    5 Fenny: [5c Qd Ts]
    Discard: [3d]
    Board: [6c Jd 2s]
  t: Turn (p: 1, d: 1, b: 1)
    0 Alice: [Qc 9d 4d 2h]
    1 Bob: [4h 5h 6h 9h]
    2 Carl: [2c 3c Th 3s]
    3 Dave: [7c Tc Ah 5s]
    4 Elizabeth: [Kc 9c Ac 8d]
    5 Fenny: [5c Qd Ts 8c]
    Discard: [3d Qs]
    Board: [6c Jd 2s 8h]
  r: River (d: 1, b: 1)
    Discard: [3d Qs Kh]
    Board: [6c Jd 2s 8h 6s]
Showdown:
  Run 0:
    0: inactive
    1: inactive
    2: [Jh Js 3c 3h 7s] [Qh 8s 5d 2c] Two Pair, Jacks over Threes, kicker Seven
       [] [] None
    3: [Jc Jh Js Ks Qh] [Tc 8s 7c 3h] Three of a Kind, Jacks, kickers King, Queen
       [] [] None
    4: inactive
    5: [Qd Qh Jh Js Ad] [Kd 8s 5c 3h] Two Pair, Queens over Jacks, kicker Ace
       [] [] None
    Result: Dave scoops with Three of a Kind, Jacks, kickers King, Queen
  Run 1:
    0: inactive
    1: inactive
    2: [6c 6s 3c 3s Jd] [Th 8h 2c 2s] Two Pair, Sixes over Threes, kicker Jack
       [] [] None
    3: [6c 6s Ah Jd Tc] [8h 7c 5s 2s] Pair, Sixes, kickers Ace, Jack, Ten
       [8h 6c 5s 2s Ah] [Jd Tc 7c 6s] Eight, Six, Five, Two, Ace-low
    4: inactive
    5: [8c 8h 6c 6s Qd] [Jd Ts 5c 2s] Two Pair, Eights over Sixes, kicker Queen
       [] [] None
    Result: Fenny wins with Two Pair, Eights over Sixes, kicker Queen
            Dave wins with Eight, Six, Five, Two, Ace-low
Example (ComputerHand)
package main

import (
	"context"
	"fmt"

	"github.com/cardrank/cardrank"
)

func main() {
	pocket := cardrank.Must("Qh 7s")
	expv, ok := cardrank.Holdem.ExpValue(context.Background(), pocket)
	if !ok {
		panic("unable to calculate expected value")
	}
	fmt.Println("expected value:", expv)
}
Output:

expected value: 51.8% (1046780178,78084287/2097572400)

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 (
	// DeckFrench is a standard deck of 52 playing cards.
	DeckFrench = DeckType(Two)
	// DeckShort is a deck of 36 playing cards of rank 6+ (see [Short]).
	DeckShort = DeckType(Six)
	// DeckManila is a deck of 32 playing cards of rank 7+ (see [Manila]).
	DeckManila = DeckType(Seven)
	// DeckSpanish is a deck of 28 playing cards of rank 8+ (see [Spanish]).
	DeckSpanish = DeckType(Eight)
	// DeckRoyal is a deck of 20 playing cards of rank 10+ (see [Royal]).
	DeckRoyal = DeckType(Ten)
	// DeckKuhn is a deck of 3 playing cards, a [King], [Queen], and a [Jack]
	// (see [Kuhn]).
	DeckKuhn = DeckType(^uint8(0) - 1)
	// DeckLeduc is a deck of 6 playing cards, a [King], [Queen], and a [Jack]
	// of the [Spade] and [Heart] suits (see [Leduc]).
	DeckLeduc = DeckType(^uint8(0) - 2)
)

Deck types.

View Source
const InvalidCard = ^Card(0)

InvalidCard is an invalid card.

View Source
const InvalidRank = ^Rank(0)

InvalidRank is an invalid card rank.

View Source
const InvalidSuit = ^Suit(0)

InvalidSuit is an invalid card suit.

Variables

View Source
var AlternateEmoji = [4]string{
	"♠️",
	"♥️",
	"🔷",
	"☘️",
}

AlternateEmoji are alternate emoji pips.

Functions

func CactusDesc

func CactusDesc(f fmt.State, verb rune, rank EvalRank, best, unused []Card)

CactusDesc writes a Cactus description to f for the rank, best, and unused cards.

Examples:

Straight Flush, Ace-high, Royal
Straight Flush, King-high, Platinum Oxide
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
Seven-high, kickers Six, Five, Three, Two

func FlushOverDesc

func FlushOverDesc(f fmt.State, verb rune, rank EvalRank, best, unused []Card)

FlushOverDesc writes a FlushOver description to f for the rank, best, and unused cards.

func HashKey

func HashKey(c0, c1 Card) string

HashKey returns the hash key of the pocket cards.

func HighDesc

func HighDesc(f fmt.State, verb rune, rank EvalRank, best, unused []Card)

HighDesc writes a [High] description to f for the rank, best, and unused cards.

func HoldemBlinds

func HoldemBlinds() []string

HoldemBlinds returns the Holdem blind names.

func HoldemStarting

func HoldemStarting() map[string]ExpValue

HoldemStarting returns the starting Holdem pockets.

func Init

func Init()

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

func LowDesc

func LowDesc(f fmt.State, verb rune, rank EvalRank, best, unused []Card)

LowDesc writes a Low description to f for the rank, best, and unused cards.

func LowballDesc

func LowballDesc(f fmt.State, verb rune, rank EvalRank, best, unused []Card)

LowballDesc writes a Lowball description to f for the rank, best, and unused cards.

func Order

func Order(evs []*Eval, low bool) ([]int, int)

Order builds an ordered slice of indices for the provided evals, ordered by either Hi or Lo (per Eval.Comp), returning the slice of indices and a pivot into the indices indicating the winning vs losing position.

Pivot will always be 1 or higher when ordering by Hi's. When ordering by Lo's, if there are no valid (ie, qualified) evals, the returned pivot will be 0.

func RazzDesc

func RazzDesc(f fmt.State, verb rune, rank EvalRank, best, unused []Card)

RazzDesc writes a Razz description to f for the rank, best, and unused cards.

func RegisterDefaultTypes

func RegisterDefaultTypes() error

RegisterDefaultTypes registers default types.

See DefaultTypes.

func RegisterType

func RegisterType(desc TypeDesc) error

RegisterType registers a type.

func SokoDesc

func SokoDesc(f fmt.State, verb rune, rank EvalRank, best, unused []Card)

SokoDesc writes a Soko description to f for the rank, best, and unused cards.

func StudBlinds

func StudBlinds() []string

StudBlinds returns the Stud blind names.

func ThreeDesc

func ThreeDesc(f fmt.State, verb rune, rank EvalRank, best, unused []Card)

ThreeDesc writes a Three description to f for the rank, best, and unused cards.

Types

type BinGen

type BinGen[T any] struct {
	// contains filtered or unexported fields
}

BinGen is a binomial combination generator.

func NewBinGen

func NewBinGen[T any](s []T, k int) *BinGen[T]

NewBinGen creates a uninitialized binomial combination generator. The generator must be manually initialized by calling Init.

func NewBinGenInit

func NewBinGenInit[T any](s []T, k int, unused bool, d []T) *BinGen[T]

NewBinGenInit creates and initializes a binomial combination generator using f and d.

func NewCombinGen

func NewCombinGen[T any](s []T, k int) (*BinGen[T], []T)

NewCombinGen creates a binomial combination generator.

func NewCombinUnusedGen

func NewCombinUnusedGen[T any](s []T, k int) (*BinGen[T], []T)

NewCombinUnusedGen creates a binomial combination generator that also copies the unused values.

func (*BinGen[T]) Copy

func (g *BinGen[T]) Copy()

Copy copies the next combination, storing in d.

func (*BinGen[T]) Next

func (g *BinGen[T]) Next() bool

Next generates the next binomial combination.

func (*BinGen[T]) Unused

func (g *BinGen[T]) Unused()

Unused copies the next combination, storing in d along with the unused values.

type CalcOption

type CalcOption func(interface{})

CalcOption is a calc option.

func WithActive

func WithActive(active map[int]bool, folded bool) CalcOption

WithActive is a calc option to run with the active map and whether or not folded positions should be included.

func WithBoard

func WithBoard(board []Card) CalcOption

WithBoard is a calc option to set the board.

func WithDeep

func WithDeep(deep bool) CalcOption

WithDeep is a calc option to set whether the run should run deep calculations.

func WithDiscard

func WithDiscard(discard bool) CalcOption

WithDiscard is a calc option to set whether the run's discarded cards should be excluded.

func WithOpponents

func WithOpponents(opponents int) CalcOption

WithOpponents is a calc option to set the opponents.

func WithPocketsBoard

func WithPocketsBoard(pockets [][]Card, board []Card) CalcOption

WithPocketsBoard is a calc option to run with the pockets, board.

func WithRuns

func WithRuns(runs []*Run) CalcOption

WithRuns is a calc option to set the runs.

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 v []cardrank.Card
	if err := json.Unmarshal([]byte(`["3s", "4c", "5c", "Ah", "2d"]`), &v); err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", v)
}
Output:

[3s 4c 5c Ah 2d]

func Exclude

func Exclude(v []Card, ex ...[]Card) []Card

Exclude is returns v excluding any specified cards.

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 parses common string representations of Card's contained in v, ignoring case and whitespace and panicing on any error.

Returns a single slice of all cards from all strings in v.

See Parse for overview of accepted string representations.

Example
package main

import (
	"fmt"

	"github.com/cardrank/cardrank"
)

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

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

func New

func New(rank Rank, suit Suit) Card

New creates a card for the rank and suit.

func Parse

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

Parse parses common string representations of Card's contained in v, ignoring case and whitespace.

Accepts the following:

  • a rank followed by a suit (ex: "Ah", "ks", "10s", "Tc", "8d", "6c")
  • a rank followed by a white or black unicode suit pip (ex: "J♤", "K♠")
  • unicode playing card runes (ex: "🃆", "🂣").

Returns a single slice of all cards from all strings in v.

func (Card) AceRank

func (c Card) AceRank() int

AceRank returns the card Ace-low index.

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 (♤♡♢♧)
e - rank (as in s) and the emoji pip (♠️ ❤️ ♦️ ♣️ ) (ex: K♠️ A❤️ )
E - emoji pip (as in e) without rank (♠️ ❤️ ♦️ ♣️ )
a - rank (as in s) and the alternate emoji pip (see [AlternateEmoji])
A - alternate emoji pip (see [AlternateEmoji])
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
F - straight flush rank name

func (Card) Index

func (c Card) Index() int

Index returns the card index.

func (Card) KnightRune

func (c Card) KnightRune() rune

KnightRune returns the card's unicode playing card rune, substituting knights for Jack's.

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 card rank.

func (Card) RankByte

func (c Card) RankByte() byte

RankByte returns the card rank byte.

func (Card) RankIndex

func (c Card) RankIndex() int

RankIndex returns the card rank index.

func (Card) Rune

func (c Card) Rune() rune

Rune returns the card's unicode playing card rune.

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 card suit.

func (Card) SuitByte

func (c Card) SuitByte() byte

SuitByte returns the card suit byte.

func (Card) SuitIndex

func (c Card) SuitIndex() int

SuitIndex returns the card suit index.

func (*Card) UnmarshalText

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

UnmarshalText satisfies the encoding.TextUnmarshaler interface.

type Dealer

type Dealer struct {
	TypeDesc
	Deck    *Deck
	Count   int
	Active  map[int]bool
	Runs    []*Run
	Results []*Result
	// contains filtered or unexported fields
}

Dealer maintains deal state for a type, streets, deck, positions, runs, results, and wins. Use as a street and run iterator for a Type. See usage details in the package example.

func NewDealer

func NewDealer(desc TypeDesc, deck *Deck, count int) *Dealer

NewDealer creates a new dealer for a provided deck and pocket count.

func NewShuffledDealer

func NewShuffledDealer(desc TypeDesc, shuffler Shuffler, shuffles, count int) *Dealer

NewShuffledDealer creates a new deck and dealer, shuffling the deck multiple times and returning the dealer with the created deck and pocket count.

func (*Dealer) Board

func (d *Dealer) Board() int

Board returns the number of board cards to be dealt on the current street.

func (*Dealer) BoardDiscard

func (d *Dealer) BoardDiscard() int

BoardDiscard returns the number of board cards to be discarded prior to dealing a board on the current street.

func (*Dealer) Calc

func (d *Dealer) Calc(ctx context.Context, folded bool, opts ...CalcOption) (*Odds, *Odds, bool)

Calc calculates the run odds, including whether or not to include folded positions.

func (*Dealer) ChangeRuns

func (d *Dealer) ChangeRuns(runs int) bool

ChangeRuns changes the number of runs, returning true if successful.

func (*Dealer) Deactivate

func (d *Dealer) Deactivate(positions ...int) bool

Deactivate deactivates positions, which will not be dealt further cards and will not be included during eval.

func (*Dealer) Deal

func (d *Dealer) Deal(street int, run *Run)

Deal deals pocket and board cards for the street and run, discarding cards accordingly.

func (*Dealer) Discarded

func (d *Dealer) Discarded() []Card

Discarded returns the cards discarded on the current street and run.

func (*Dealer) Format

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

Format satisfies the fmt.Formatter interface.

func (*Dealer) HasActive

func (d *Dealer) HasActive() bool

HasActive returns true when there is more than 1 active positions.

func (*Dealer) HasBoard

func (d *Dealer) HasBoard() bool

HasBoard returns true when one or more board cards are dealt for the current street.

func (*Dealer) HasCalc

func (d *Dealer) HasCalc() bool

HasCalc returns true when odds are available for calculation.

func (*Dealer) HasNext

func (d *Dealer) HasNext() bool

HasNext returns true when there is one or more remaining streets.

func (*Dealer) HasPocket

func (d *Dealer) HasPocket() bool

HasPocket returns true when one or more pocket cards are dealt for the current street.

func (*Dealer) Id

func (d *Dealer) Id() byte

Id returns the current street id.

func (*Dealer) Inactive

func (d *Dealer) Inactive() []int

Inactive returns the inactive positions.

func (*Dealer) Name

func (d *Dealer) Name() string

Name returns the current street name.

func (*Dealer) Next

func (d *Dealer) Next() bool

Next iterates the current street and run, discarding cards prior to dealing additional pocket and board cards for each street and run. Returns true when there are at least 2 active positions for a Type having Max greater than 1 and when there are additional streets or runs.

func (*Dealer) NextId

func (d *Dealer) NextId() byte

NextId returns the next street id.

func (*Dealer) NextResult

func (d *Dealer) NextResult() bool

NextResult iterates the next result.

func (*Dealer) Pocket

func (d *Dealer) Pocket() int

Pocket returns the number of pocket cards to be dealt on the current street.

func (*Dealer) PocketDiscard

func (d *Dealer) PocketDiscard() int

PocketDiscard returns the number of cards to be discarded prior to dealing pockets on the current street.

func (*Dealer) PocketDraw

func (d *Dealer) PocketDraw() int

PocketDraw returns the number of pocket cards that can be drawn on the current street.

func (*Dealer) PocketUp

func (d *Dealer) PocketUp() int

PocketUp returns the number of pocket cards to be turned up on the current street.

func (*Dealer) Reset

func (d *Dealer) Reset()

Reset resets the dealer and deck.

func (*Dealer) Result

func (d *Dealer) Result() (int, *Result)

Result returns the current result.

func (*Dealer) Run

func (d *Dealer) Run() (int, *Run)

Run returns the current run.

func (*Dealer) Street

func (d *Dealer) Street() int

Street returns the current street.

type Deck

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

Deck is a set of playing cards.

func DeckOf

func DeckOf(cards ...Card) *Deck

DeckOf creates a deck for the provided cards.

func NewDeck

func NewDeck() *Deck

NewDeck creates a French deck of 52 unshuffled cards.

func NewShoe

func NewShoe(count int) *Deck

NewShoe creates a card shoe with multiple sets of 52 unshuffled cards.

func (*Deck) All

func (d *Deck) All() []Card

All returns a copy of all cards in the deck, without advancing.

func (*Deck) Draw

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

Draw draws count 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
	r := rand.New(rand.NewSource(52))
	d.Shuffle(r, 1)
	v := d.Draw(7)
	fmt.Printf("%b\n", v)
}
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) Limit

func (d *Deck) Limit(limit int)

Limit limits the cards for the deck, for use with card shoes composed of more than one deck of cards.

func (*Deck) Remaining

func (d *Deck) Remaining() int

Remaining returns the number of remaining cards in the deck.

func (*Deck) Reset

func (d *Deck) Reset()

Reset resets the deck.

func (*Deck) Shuffle

func (d *Deck) Shuffle(shuffler Shuffler, shuffles int)

Shuffle shuffles the deck's cards using the shuffler.

type DeckType

type DeckType uint8

DeckType is a deck type.

func (DeckType) Desc

func (typ DeckType) Desc(short bool) string

Desc returns the deck description.

func (DeckType) Exclude

func (typ DeckType) Exclude(ex ...[]Card) []Card

Exclude returns a set of unshuffled cards excluding any supplied cards.

func (DeckType) Format

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

Format satisfies the fmt.Formatter interface.

func (DeckType) Name

func (typ DeckType) Name() string

Name returns the deck name.

func (DeckType) New

func (typ DeckType) New() *Deck

New returns a new deck.

func (DeckType) Ordinal

func (typ DeckType) Ordinal() int

Ordinal returns the deck ordinal.

func (DeckType) Shoe

func (typ DeckType) Shoe(count int) *Deck

Shoe creates a card shoe composed of count number of decks of unshuffled cards.

func (DeckType) Shuffle

func (typ DeckType) Shuffle(shuffler Shuffler, shuffles int) *Deck

Shuffle returns a new deck, shuffled by the shuffler.

func (DeckType) Unshuffled

func (typ DeckType) Unshuffled() []Card

Unshuffled returns a set of the deck's unshuffled cards.

type DescType

type DescType uint8

DescType is a description type.

const (
	DescCactus    DescType = 0
	DescFlushOver DescType = 'f'
	DescSoko      DescType = 'k'
	DescLow       DescType = 'l'
	DescLowball   DescType = 'b'
	DescRazz      DescType = 'r'
	DescHigh      DescType = 'h'
	DescThree     DescType = '3'
)

Description types.

func (DescType) Byte

func (typ DescType) Byte() byte

Byte returns the description type byte.

func (DescType) Desc

func (typ DescType) Desc(f fmt.State, verb rune, rank EvalRank, best, unused []Card)

Desc writes a description to f for the rank, best, and unused cards.

Supported verbs:

d - rank formatted as a int (1, 3775, ...)
e - best description, eval rank only (Two Pair, Pair, Flush, 7-Low, ...)
s - best full description (Four of a Kind, Ace, kickers King)
S - best description, no kickers
u - unused cards with [CardFormatter]
v - same as s

func (DescType) Format

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

Format satisfies the fmt.Formatter interface.

func (DescType) Name

func (typ DescType) Name() string

Name returns the description type name.

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 Eval

type Eval struct {
	Type     Type
	HiRank   EvalRank
	HiBest   []Card
	HiUnused []Card
	LoRank   EvalRank
	LoBest   []Card
	LoUnused []Card
}

Eval contains the eval results of a type's Hi/Lo.

func EvalOf

func EvalOf(typ Type) *Eval

EvalOf creates a eval for the type.

func (*Eval) Comp

func (ev *Eval) Comp(b *Eval, low bool) int

Comp compares the eval's Hi/Lo to b's Hi/Lo.

func (*Eval) Desc

func (ev *Eval) Desc(low bool) *EvalDesc

Desc returns a descriptior for the eval's Hi/Lo.

func (*Eval) Eval

func (ev *Eval) Eval(pocket, board []Card)

Eval evaluates the pocket, board.

func (*Eval) Format

func (ev *Eval) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

func (*Eval) Hi5

func (ev *Eval) Hi5(f RankFunc, v []Card)

Hi5 evaluates the 5 cards in v, using f.

func (*Eval) Hi6

func (ev *Eval) Hi6(f RankFunc, v []Card)

Hi6 evaluates the 6 cards in v, using f.

func (*Eval) Hi7

func (ev *Eval) Hi7(f RankFunc, v []Card)

Hi7 evaluates the 7 cards in v, using f.

func (*Eval) HiLo23

func (ev *Eval) HiLo23(hi, lo RankFunc, c0, c1 Card, b []Card, max EvalRank)

HiLo23 evaluates the 2 cards c0, c1 and the 3 in b, using hi, lo.

func (*Eval) HiLo24

func (ev *Eval) HiLo24(hi, lo RankFunc, c0, c1 Card, b []Card, max EvalRank)

HiLo24 evaluates the 2 cards c0, c1 and the 4 in b, using hi, lo.

func (*Eval) HiLo25

func (ev *Eval) HiLo25(hi, lo RankFunc, c0, c1 Card, b []Card, max EvalRank)

HiLo25 evaluates the 2 cards c0, c1 and the 5 in b, using hi, lo.

func (*Eval) HiLo5

func (ev *Eval) HiLo5(hi, lo RankFunc, v []Card, max EvalRank)

HiLo5 evaluates the 5 cards in v, using hi, lo.

func (*Eval) HiLo6

func (ev *Eval) HiLo6(hi, lo RankFunc, v []Card, max EvalRank)

HiLo6 evaluates the 6 cards in v, using hi, lo.

func (*Eval) HiLo7

func (ev *Eval) HiLo7(hi, lo RankFunc, v []Card, max EvalRank)

HiLo7 evaluates the 7 cards in v, using hi, lo.

func (*Eval) Max5

func (ev *Eval) Max5(f RankFunc, v []Card, max EvalRank, low bool)

Max5 evaluates the 5 cards in v, using f, storing only when below max.

func (*Eval) Max6

func (ev *Eval) Max6(f RankFunc, v []Card, max EvalRank, low bool)

Max6 evaluates the 6 cards in v, using f, storing only when below max.

func (*Eval) Max7

func (ev *Eval) Max7(f RankFunc, v []Card, max EvalRank, low bool)

Max7 evaluates the 7 cards in v, using f, storing only when below max.

type EvalDesc

type EvalDesc struct {
	Type   DescType
	Rank   EvalRank
	Best   []Card
	Unused []Card
}

EvalDesc describes a Hi/Lo eval.

func (*EvalDesc) Format

func (desc *EvalDesc) Format(f fmt.State, verb rune)

Format satisfies the fmt.Stringer interface.

type EvalFunc

type EvalFunc func(*Eval, []Card, []Card)

EvalFunc is a eval func.

func NewBadugiEval

func NewBadugiEval(normalize bool) EvalFunc

NewBadugiEval creates a Badugi eval func.

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

func NewCactusEval

func NewCactusEval(normalize, low bool) EvalFunc

NewCactusEval creates a Cactus eval func.

func NewEval

func NewEval(f RankFunc) EvalFunc

NewEval returns a eval func that ranks 5, 6, or 7 cards using f. The returned eval func will store the results on an eval's Hi.

func NewHighEval

func NewHighEval() EvalFunc

NewHighEval creates a high card eval func.

func NewHybridEval

func NewHybridEval(normalize, low bool) EvalFunc

NewHybridEval creates a hybrid Cactus and TwoPlusTwo eval func, using RankCactus for 5 and 6 cards, and a TwoPlusTwo eval func for 7 cards.

Gives optimal performance when evaluating the best-5 of any 5, 6, or 7 cards of a combined pocket and board.

func NewJacksOrBetterEval

func NewJacksOrBetterEval(normalize bool) EvalFunc

NewJacksOrBetterEval creates a JacksOrBetter eval func, used for Video.

func NewLeducEval

func NewLeducEval() EvalFunc

NewLeducEval creates a matching high card eval func.

func NewLowballEval

func NewLowballEval(normalize bool) EvalFunc

NewLowballEval creates a Lowball eval func.

func NewMaxEval

func NewMaxEval(f RankFunc, max EvalRank, low bool) EvalFunc

NewMaxEval returns a eval func that ranks 5, 6, or 7 cards using f and max.

The returned eval func will store results on an eval's Hi only when lower than max.

func NewModifiedEval

func NewModifiedEval(hi RankFunc, base Rank, inv func(EvalRank) EvalRank, normalize, low bool) EvalFunc

NewModifiedEval creates a modified Cactus eval.

func NewOmahaEval

func NewOmahaEval(hi RankFunc, base Rank, inv func(EvalRank) EvalRank, normalize, low bool) EvalFunc

NewOmahaEval creates a Omaha eval func.

Uses any 2 from 2, 3, 4, 5, or 6 pocket cards, and any 3 from 3, 4 or 5 board cards to make a best-5.

func NewRazzEval

func NewRazzEval(normalize bool) EvalFunc

NewRazzEval creates a Razz eval func.

func NewSokoEval

func NewSokoEval(normalize, low bool) EvalFunc

NewSokoEval creates a Soko eval func.

func NewSplitEval

func NewSplitEval(hi, lo RankFunc, max EvalRank) EvalFunc

NewSplitEval returns a eval func that ranks 5, 6, or 7 cards using hi, lo and max.

The returned eval func will store results on an eval's Hi and Lo depending on the result of hi and lo, respectively. Will store the Lo value only when lower than max.

func NewThreeEval

func NewThreeEval() EvalFunc

NewThreeEval creates a best-3 eval func.

Straight Flush
Three of a Kind
Straight
Flush
One Pair
High Card

type EvalRank

type EvalRank uint16

EvalRank is a eval rank.

Ranks are ordered low-to-high.

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

Eval ranks.

See: https://archive.is/G6GZg

func Cactus

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

Cactus is a Cactus Kev rank eval func, using lookup maps generated on the fly.

See: https://archive.is/G6GZg

func CactusFast

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

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

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

func RankAceFiveLow

func RankAceFiveLow(mask EvalRank, c0, c1, c2, c3, c4 Card) EvalRank

RankAceFiveLow is a A-to-5 low rank eval func. Ace's are low, Straight's and Flush's do not count.

func RankEightOrBetter

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

RankEightOrBetter is a 8-or-better low rank eval func. Ace's are low, Straight's and Flush's do not count.

func RankLowball

func RankLowball(c0, c1, c2, c3, c4 Card) EvalRank

RankLowball is a Lowball (2-to-7) low rank eval func. Ace's are high, Straight's and Flush's count.

Works by adding 2 additional ranks for Ace-high StraightFlush's and Straight's.

See EvalRank.ToLowball.

func RankManila

func RankManila(c0, c1, c2, c3, c4 Card) EvalRank

RankManila is a Manila rank eval func.

func RankRazz

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

RankRazz is a Razz (A-to-5) low rank eval func. Ace's are low, Straight's and Flush's do not count.

When there is a Pair (or higher) of matching ranks, will be the inverted Cactus value.

func RankShort

func RankShort(c0, c1, c2, c3, c4 Card) EvalRank

RankShort is a Short rank eval func.

func RankSoko

func RankSoko(c0, c1, c2, c3, c4 Card) EvalRank

RankSoko is a Soko rank eval func.

Has ranks to Cactus, adding a Four Flush and Four Straight that beat Pair's and Nothing:

Straight Flush
Four of a Kind
Full House
Flush
Straight
Three of a Kind
Two Pair
Four Flush
Four Straight
Pair
Nothing

func RankSpanish

func RankSpanish(c0, c1, c2, c3, c4 Card) EvalRank

RankSpanish is a Spanish rank eval func.

func (EvalRank) Fixed

func (r EvalRank) Fixed() EvalRank

Fixed converts a relative eval rank to a fixed eval rank.

func (EvalRank) Format

func (r EvalRank) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

func (EvalRank) FromFlushOver

func (r EvalRank) FromFlushOver() EvalRank

FromFlushOver changes a rank from a Flush Over a Full House rank to a Cactus rank.

FullHouse: FullHouse(322) - FourOfAKind(166) == 156
Flush:     Flush(1599)    - FullHouse(322)   == 1277

func (EvalRank) FromLowball

func (r EvalRank) FromLowball() EvalRank

FromLowball converts a Lowball rank to a Cactus rank.

See EvalRank.ToLowball for a description of the operations performed.

func (EvalRank) Name

func (r EvalRank) Name() string

Name returns the eval rank name.

Examples:

StraightFlush
FourOfAKind

func (EvalRank) Title

func (r EvalRank) Title() string

Title returns the eval rank title.

Examples:

Straight Flush
Four of a Kind

func (EvalRank) ToFlushOver

func (r EvalRank) ToFlushOver() EvalRank

ToFlushOver changes a Cactus rank to a Flush Over a Full House rank.

FullHouse: FullHouse(322) - FourOfAKind(166) == 156
Flush:     Flush(1599)    - FullHouse(322)   == 1277

func (EvalRank) ToLowball

func (r EvalRank) ToLowball() EvalRank

ToLowball converts a Cactus rank to a Lowball rank, by inverting the rank and converting the lowest Straight and Straight Flushes (5-4-3-2-A) to different ranks.

Changes the rank as follows:

Moves lowest Straight Flush (10) to lowest Ace Flush (811)
Moves any rank between Straight Flush (10) < r <= lowest Ace Flush (811) down 1 rank
Moves lowest Straight (1609) to lowest Ace Nothing (6678)
Moves any rank between Straight (1609) < r <= lowest Ace Nothing (6678) down 1 rank
Inverts the rank (Nothing - r + 1)

type EvalType

type EvalType uint8

EvalType is a eval type.

const (
	EvalCactus        EvalType = 0
	EvalJacksOrBetter EvalType = 'j'
	EvalShort         EvalType = 't'
	EvalManila        EvalType = 'm'
	EvalSpanish       EvalType = 'p'
	EvalOmaha         EvalType = 'o'
	EvalSoko          EvalType = 'k'
	EvalLowball       EvalType = 'l'
	EvalRazz          EvalType = 'r'
	EvalBadugi        EvalType = 'b'
	EvalHigh          EvalType = 'h'
	EvalThree         EvalType = '3'
)

Eval types.

func (EvalType) Byte

func (typ EvalType) Byte() byte

Byte returns the eval type byte.

func (EvalType) Cactus

func (typ EvalType) Cactus() bool

Cactus returns true when the eval is a Cactus eval.

func (EvalType) Format

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

Format satisfies the fmt.Formatter interface.

func (EvalType) Name

func (typ EvalType) Name() string

Name returns the eval type name.

func (EvalType) New

func (typ EvalType) New(normalize, low bool) EvalFunc

New creates a eval func for the type.

type ExpValue

type ExpValue struct {
	Opponents int
	Wins      uint64
	Splits    uint64
	Losses    uint64
	Total     uint64
}

ExpValue is the result of a expected value calculation.

func NewExpValue

func NewExpValue(opponents int) *ExpValue

NewExpValue creates a new expected value.

func StartingExpValue

func StartingExpValue(pocket []Card) *ExpValue

StartingExpValue returns the starting pocket expected value.

func (*ExpValue) Add

func (expv *ExpValue) Add(v *ExpValue)

Add adds b to the expected value.

func (*ExpValue) Float64

func (expv *ExpValue) Float64() float64

Float32 returns the expected value as a float32.

func (*ExpValue) Format

func (expv *ExpValue) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

func (*ExpValue) Percent

func (expv *ExpValue) Percent() float64

Percent returns the expected value calculated as a percent.

type ExpValueCalc

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

ExpValueCalc is a expected value calculator.

Example
package main

import (
	"context"
	"fmt"

	"github.com/cardrank/cardrank"
)

func main() {
	pocket, board := cardrank.Must("Kh 3h"), cardrank.Must("Ah 8h 3c")
	expv, ok := cardrank.Holdem.ExpValue(context.Background(), pocket, cardrank.WithBoard(board))
	if !ok {
		panic("unable to calculate expected value")
	}
	fmt.Println("expected value:", expv)
}
Output:

expected value: 75.6% (802371,13659/1070190)

func NewExpValueCalc

func NewExpValueCalc(typ Type, pocket []Card, opts ...CalcOption) *ExpValueCalc

NewExpValueCalc creates a new expected value calculator.

func (*ExpValueCalc) Calc

func (c *ExpValueCalc) Calc(ctx context.Context) (*ExpValue, bool)

Calc calculates the expected value.

func (*ExpValueCalc) NewExpValue

func (c *ExpValueCalc) NewExpValue() *ExpValue

NewExpValue creates a new expected value.

type Formatter

type Formatter []Card

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

func (Formatter) Format

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

Format satisfies the fmt.Formatter interface.

type Odds

type Odds struct {
	// Total is the total number of outcomes.
	Total int
	// Counts is each position's outcome count for wins and splits.
	Counts []int
	// Outs are map of the available outs for a position.
	Outs []map[Card]bool
}

Odds are calculated run odds.

func NewOdds

func NewOdds(count int, u []Card) *Odds

NewOdds creates a new odds.

func (*Odds) Add

func (odds *Odds) Add(evs []*Eval, suits [][4]int, v []Card, low bool)

Add adds the eval results to the odds.

func (*Odds) Float32

func (odds *Odds) Float32() []float32

Float32 returns the odds as a slice of float32.

func (*Odds) Format

func (odds *Odds) Format(f fmt.State, verb rune)

Format satisfies the fmt.Formatter interface.

func (*Odds) Percent

func (odds *Odds) Percent(pos int) float32

Percent returns the odds for pos calculated as a percent.

type OddsCalc

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

OddsCalc calculates run odds.

Example
package main

import (
	"context"
	"fmt"

	"github.com/cardrank/cardrank"
)

func main() {
	pockets := [][]cardrank.Card{
		cardrank.Must("Ah As Jc Qs"),
		cardrank.Must("3h 2h Ks Tc"),
	}
	board := cardrank.Must("6h 6s Jh")
	odds, _, ok := cardrank.Omaha.Odds(context.Background(), pockets, board)
	if !ok {
		panic("unable to calculate odds")
	}
	for i := range pockets {
		fmt.Printf("%d: %*v\n", i, i, odds)
	}
}
Output:

0: 66.1% (542/820)
1: 33.9% (278/820)

func NewOddsCalc

func NewOddsCalc(typ Type, opts ...CalcOption) *OddsCalc

NewOddsCalc creates a new run odds calc.

func (*OddsCalc) Calc

func (c *OddsCalc) Calc(ctx context.Context) (*Odds, *Odds, bool)

Calc calculates odds.

type ParseError

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

ParseError is a parse error.

func (*ParseError) Error

func (err *ParseError) Error() string

Error satisfies the [error] interface.

func (*ParseError) Unwrap

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 a rune's card rank.

func (Rank) Byte

func (rank Rank) Byte() byte

Byte returns the card rank byte.

func (Rank) Index

func (rank Rank) Index() int

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

func (Rank) Name

func (rank Rank) Name() string

Name returns the card rank name.

func (Rank) PluralName

func (rank Rank) PluralName() string

PluralName returns the card rank plural name.

func (Rank) StraightFlushName

func (rank Rank) StraightFlushName() string

StraightFlushName returns the card rank StraightFlush name.

func (Rank) String

func (rank Rank) String() string

String satisfies the fmt.Stringer interface.

type RankFunc

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

RankFunc returns the eval rank of 5 cards.

var (
	// RankCactus is the default Cactus Kev func.
	RankCactus RankFunc
)

type Result

type Result struct {
	Evals   []*Eval
	HiOrder []int
	HiPivot int
	LoOrder []int
	LoPivot int
}

Result contains dealer eval results.

func NewResult

func NewResult(typ Type, run *Run, active map[int]bool, calc bool) *Result

NewResult creates a result for the run, storing the calculated or evaluated result.

func (*Result) Win

func (res *Result) Win(names ...string) (*Win, *Win)

Win returns the Hi and Lo win.

type Run

type Run struct {
	Discard []Card
	Pockets [][]Card
	Hi      []Card
	Lo      []Card
}

Run holds pockets, and a Hi/Lo board for a deal.

func NewRun

func NewRun(count int) *Run

NewRun creates a new run for the pocket count.

func (*Run) CalcStart

func (run *Run) CalcStart(low bool) (*Odds, *Odds)

CalcStart returns the run's starting odds.

func (*Run) Dupe

func (run *Run) Dupe() *Run

Dupe creates a duplicate of run, with a copy of the pockets and Hi and Lo board.

func (*Run) Eval

func (run *Run) Eval(typ Type, active map[int]bool, calc bool) []*Eval

Eval returns the evals for the run.

type Shuffler

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

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 cards to deal.
	Pocket int
	// PocketUp is the count of cards to reveal.
	PocketUp int
	// PocketDiscard is the count of cards to discard before pockets dealt.
	PocketDiscard int
	// PocketDraw is the count of cards to draw.
	PocketDraw int
	// Board is the count of board cards to deal.
	Board int
	// BoardDiscard is the count of cards to discard before board dealt.
	BoardDiscard int
}

StreetDesc is a type's street description.

func HoldemStreets

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

HoldemStreets creates Holdem streets (Pre-Flop, Flop, Turn, and River).

func NumberedStreets

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

NumberedStreets creates numbered streets (Ante, 1st, 2nd, ..., River) for each of the pockets.

func StudStreets

func StudStreets() []StreetDesc

StudStreets creates Stud streets (Ante, 3rd, 4th, 5th, 6th, and River).

func (StreetDesc) Desc

func (desc StreetDesc) Desc() string

Desc returns a description of the street.

type StreetOption

type StreetOption func(int, *StreetDesc)

StreetOption is a street option.

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 a rune's card suit.

func (Suit) AlternateEmoji

func (suit Suit) AlternateEmoji() string

ALterEmoji returns the card suit alternate pip emoji.

func (Suit) Byte

func (suit Suit) Byte() byte

Byte returns the card suit byte.

func (Suit) Emoji

func (suit Suit) Emoji() string

Emoji returns the card suit pip emoji.

func (Suit) Index

func (suit Suit) Index() int

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

func (Suit) Name

func (suit Suit) Name() string

Name returns the card suit name.

func (Suit) PluralName

func (suit Suit) PluralName() string

PluralName returns the card suit plural name.

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 card suit black unicode pip rune.

func (Suit) UnicodeWhite

func (suit Suit) UnicodeWhite() rune

UnicodeWhite returns the card suit white unicode pip rune.

type Type

type Type uint16

Type wraps a registered type description (see TypeDesc), providing a standard way to use the DefaultTypes, or a custom type registered with RegisterType. DefaultTypes are registered by default unless using the noinit build tag.

Standard Types

Holdem is a best-5 card game using a standard deck of 52 cards (see DeckFrench), having a pocket of 2 cards, 5 community board cards, and a Pre-Flop, Flop, Turn, and River streets. 2 pocket cards are dealt on the Pre-Flop, with 3 board cards on the Flop, 1 board card on the Turn, and 1 board card on the River. 1 card is discarded on the Flop, Turn, and River, prior to the board cards being dealt.

Split is the Hi/Lo variant of Holdem, using a Eight-or-better qualifier (see RankEightOrBetter) for the Lo.

Short is a Holdem variant using a Short deck of 36 cards, having only cards with ranks of 6+ (see DeckShort). Flush ranks over FullHouse.

Manila is a Holdem variant using a Manila deck of 32 cards, having only cards with ranks of 7+ (see DeckManila), forcing the use of the 2 pocket cards, adding a Drop street before the Flop, and with all 5 streets receiving 1 board card each. Flush ranks over FullHouse.

Spanish is a Holdem/Manila variant, using a Spanish deck of 28 cards, having only cards with ranks of 8+ (see DeckSpanish).

Royal is a Holdem variant using a Royal deck of 20 cards, having only cards with ranks of 10+ (see DeckRoyal).

Double is a Holdem variant having two separate Hi and Lo community boards.

Showtime is a Holdem variant where folded cards are shown.

Swap is a Holdem variant where up to 2 pocket cards may be drawn (exchanged) exactly once on the Flop, Turn, or River.

River is a Holdem variant that deals 1 pocket card on the River instead of to the community board, resulting in a total pocket of 3 cards and a community board of 4 cards. Any of the 3 pocket cards or 4 board cards may be used to create the best-5.

Dallas is Holdem variant that forces the use of the 2 pocket cards and any 3 of the 5 board cards to make the best-5. Comparable to Omaha, but with 2 pocket cards instead of 4.

Houston is a Holdem/Dallas variant with 3 pocket cards, instead of 2, where only 2 board cards are dealt on the Flop, instead of 3. Requires using 2 of the 3 pocket cards and any 3 of the 4 board cards to make the best-5. Comparable to Omaha, but with 3 pocket cards instead of 4, and a community board of 4.

Draw is a best-5 card game using a standard deck of 52 cards (see DeckFrench), comprising a pocket of 5 cards, no community cards, with a Ante, 6th, and River streets. 5 cards are dealt on the Ante, and up to 5 pocket cards can be drawn (exchanged) on the 6th street.

DrawHiLo is the Hi/Lo variant of Draw, using a Eight-or-better qualifier (see RankEightOrBetter) for the Lo.

Stud is a best-5 card game, using a standard deck of 52 cards (see DeckFrench), comprising a pocket of 7 cards, no community cards, with Ante, 4th, 5th, 6th and River streets. 2 pocket cards are dealt down and 1 pocket card up on the Ante, and 1 additional pocket card dealt up on the 4th, 5th, and 6th streets, with 1 final additional pocket card dealt down on the 7th street.

StudHiLo is the Hi/Lo variant of Stud, using a Eight-or-better qualifier (see RankEightOrBetter) for the Lo.

StudFive is a best-5 card game using a standard deck of 52 cards (see DeckFrench), comprising a pocket of 5 cards, no community cards, with Ante, 3rd, 4th, and River streets. 2 pocket cards are dealt on the Ante, with 1 pocket card dealt up, and an additional pocket card dealt up on the 3rd, 4th, and 5th streets. Similar to Stud, but without 5th and 6th streets.

Video is a best-5 card game, using a standard deck of 52 cards (see DeckFrench), comprising a pocket of 5 cards, no community cards, with a Ante and River. 5 pocket cards are dealt on the Ante, all up. Up to 5 pocket cards can be drawn (exchanged) on the River. Uses a qualifier of a Jack's-or-better for Hi eval (see NewJacksOrBetterEval).

Omaha is a Holdem variant with 4 pocket cards instead of 2, requiring use of 2 of 4 the pocket cards and any 3 of the 5 board cards to make the best-5.

OmahaHiLo is the Hi/Lo variant of Omaha, using a Eight-or-better qualifier (see RankEightOrBetter) for the Lo.

OmahaDouble is a Omaha variant having two separate Hi and Lo community boards.

OmahaFive is a Holdem/Omaha variant with 5 pocket cards, requiring the use of 2 of the 5 pocket cards and any 3 of the 5 board cards to make the best-5.

OmahaSix is a Holdem/Omaha variant with 6 pocket cards, requiring the use of 2 of the 6 pocket cards and any 3 of the 5 board cards to make the best-5.

OmahaRoyal is a Omaha variant using a Royal deck of 20 cards, having only cards with ranks of 10+ (see DeckRoyal).

Courchevel is a OmahaFive variant, where 1 board card is dealt on the Pre-Flop, and only 2 board cards dealt on the Flop.

CourchevelHiLo is the Hi/Lo variant of Courchevel, using a Eight-or-better qualifier (see RankEightOrBetter) for the Lo.

Fusion is a Holdem/Omaha variant where only 2 pocket cards are dealt on the Pre-Flop, with 1 additional pocket card dealt on the Flop and Turn.

FusionHiLo is the Hi/Lo variant of Fusion, using a Eight-or-better qualifier (see RankEightOrBetter) for the Lo.

Soko is a Stud/StudFive variant with 2 additional ranks, a Four Flush (4 cards of the same suit), and a Four Straight (4 cards in sequential rank, with no wrapping straights), besting Pair and Nothing, with only a Ante and River streets where 2 pocket cards are dealt on the Ante, and 3 pocket cards are dealt, up, on the River.

SokoHiLo is the Hi/Lo variant of Soko, using a Eight-or-better qualifier (see RankEightOrBetter) for the Lo.

Lowball is a best-5 low card game using a standard deck of 52 cards (see DeckFrench), comprising 5 pocket cards, no community cards, and a Ante, 6th, 7th, and River streets using a Two-to-Seven low inverted ranking system, where Ace's are always high, and non-Flush, and non-Straight lows are best. Up to 5 pocket cards may be drawn (exchanged) exactly once on either the 6th, 7th, or River streets.

LowballTriple is a Lowball variant, where up to 5 pocket cards may be drawn (exchanged) on any of the 6th, 7th, or River streets.

Razz is a Stud low variant, using a Ace-to-Five ranking (see RankRazz), where Ace's play low, and Flush's and Straight's do not affect ranking.

Badugi is a best-4 low non-matching-suit card game, using a standard deck of 52 cards (see DeckFrench), comprising 4 pocket cards, no community cards, and Ante, 5th, 6th, and River streets. Up to 4 cards can be drawn (exchanged) multiple times on the 5th, 6th, or River streets. See NewBadugiEval for more details.

Kuhn is a best high card game, using a 3 card deck (King, Queen, Jack), having 1 pocket card and no community board cards. Useful for game tree testing. See Kuhn poker.

Leduc is a best high card game, using a 6 card deck (King, Queen, Jack each of the Spade and Heart), having 1 pocket card and 1 community card. Useful for game tree testing. See Deepstack Leduc.

RhodeIsland is a best-3 card game that is simplified version of Holdem, using a standard deck of 52 cards (see DeckFrench), having 1 pocket card, and 1 community board cards dealt each on the Flop and Turn. Useful for game tree testing. See Gilpin & Sandholm.

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
		r := rand.New(rand.NewSource(game.seed))
		pockets, _ := cardrank.Badugi.Deal(r, 1, game.players)
		evs := cardrank.Badugi.EvalPockets(pockets, nil)
		fmt.Printf("------ Badugi %d ------\n", i+1)
		for j := 0; j < game.players; j++ {
			desc := evs[j].Desc(false)
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, pockets[j], desc, desc.Best, desc.Unused)
		}
		order, pivot := cardrank.Order(evs, false)
		desc := evs[order[0]].Desc(false)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s\n", order[0]+1, desc)
		} else {
			var s []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(order[j]+1))
			}
			fmt.Printf("Result:   Players %s push with %s\n", strings.Join(s, ", "), desc)
		}
	}
}
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
------ 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
------ 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
------ 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
------ 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
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
		r := rand.New(rand.NewSource(game.seed))
		pockets, board := cardrank.Holdem.Deal(r, 1, game.players)
		evs := cardrank.Holdem.EvalPockets(pockets, board)
		fmt.Printf("------ Holdem %d ------\n", i+1)
		fmt.Printf("Board:    %b\n", board)
		for j := 0; j < game.players; j++ {
			desc := evs[j].Desc(false)
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, pockets[j], desc, desc.Best, desc.Unused)
		}
		order, pivot := cardrank.Order(evs, false)
		desc := evs[order[0]].Desc(false)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s\n", order[0]+1, desc)
		} else {
			var s []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(order[j]+1))
			}
			fmt.Printf("Result:   Players %s push with %s\n", strings.Join(s, ", "), desc)
		}
	}
}
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
------ Holdem 2 ------
Board:    [8♠ 9♠ J♠ 9♣ T♠]
Player 1: [7♠ 6♦] Straight Flush, Jack-high, Bronze Fist [J♠ T♠ 9♠ 8♠ 7♠] [9♣ 6♦]
Player 2: [T♣ Q♠] Straight Flush, Queen-high, Silver Tongue [Q♠ J♠ T♠ 9♠ 8♠] [T♣ 9♣]
Result:   Player 2 wins with Straight Flush, Queen-high, Silver Tongue
------ 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
------ 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
------ Holdem 5 ------
Board:    [3♠ 9♥ A♦ 6♥ Q♦]
Player 1: [T♦ 4♥] Ace-high, kickers Queen, Ten, Nine, Six [A♦ Q♦ T♦ 9♥ 6♥] [4♥ 3♠]
Player 2: [8♦ 7♦] 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♦] Ace-high, kickers Queen, Ten, Nine, Six [A♦ Q♦ T♣ 9♥ 6♥] [5♦ 3♠]
Player 5: [7♥ T♥] Ace-high, kickers Queen, Ten, Nine, Seven [A♦ Q♦ T♥ 9♥ 7♥] [6♥ 3♠]
Player 6: [8♣ 5♣] 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
------ Holdem 6 ------
Board:    [T♥ 6♥ 7♥ 2♥ 7♣]
Player 1: [6♣ K♥] Flush, King-high, kickers Ten, Seven, Six, Two [K♥ T♥ 7♥ 6♥ 2♥] [7♣ 6♣]
Player 2: [6♠ 5♥] Flush, Ten-high, kickers Seven, Six, Five, Two [T♥ 7♥ 6♥ 5♥ 2♥] [7♣ 6♠]
Result:   Player 1 wins with Flush, King-high, kickers Ten, Seven, Six, Two
------ 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 Ten [A♣ A♦ A♥ A♠ T♠] [4♦ 4♠]
Result:   Player 2 wins with Four of a Kind, Aces, kicker Ten
------ 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, kickers Queen, Jack, Ten, Six [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
------ Holdem 9 ------
Board:    [A♣ 2♣ 4♣ 5♣ 9♥]
Player 1: [T♣ 6♠] Flush, Ace-high, kickers Ten, Five, Four, Two [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
------ 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, kickers Nine, Eight, Seven, Six [K♥ 9♥ 8♥ 7♥ 6♥] [J♣ 8♣]
Result:   Player 3 wins with Flush, King-high, kickers Nine, Eight, Seven, Six
------ 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
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
		r := rand.New(rand.NewSource(game.seed))
		pockets, board := cardrank.Omaha.Deal(r, 1, game.players)
		evs := cardrank.Omaha.EvalPockets(pockets, board)
		fmt.Printf("------ Omaha %d ------\n", i+1)
		fmt.Printf("Board:    %b\n", board)
		for j := 0; j < game.players; j++ {
			desc := evs[j].Desc(false)
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, pockets[j], desc, desc.Best, desc.Unused)
		}
		order, pivot := cardrank.Order(evs, false)
		desc := evs[order[0]].Desc(false)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s\n", order[0]+1, desc)
		} else {
			var s []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(order[j]+1))
			}
			fmt.Printf("Result:   Players %s push with %s\n", strings.Join(s, ", "), desc)
		}
	}
}
Output:

------ Omaha 1 ------
Board:    [3♥ 5♥ 4♥ 7♥ K♣]
Player 1: [K♥ J♣ A♥ Q♠] Flush, Ace-high, kickers King, Seven, Five, Four [A♥ K♥ 7♥ 5♥ 4♥] [K♣ Q♠ J♣ 3♥]
Player 2: [7♣ 4♣ 5♠ 2♠] Two Pair, Sevens over Fives, kicker King [7♣ 7♥ 5♥ 5♠ K♣] [4♣ 4♥ 3♥ 2♠]
Result:   Player 1 wins with Flush, Ace-high, kickers King, Seven, Five, Four
------ 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♠] [Q♠ T♠ 9♣ 7♣]
Player 2: [6♦ Q♣ 8♥ 6♣] Flush, Queen-high, kickers Nine, Seven, Six, Three [Q♣ 9♣ 7♣ 6♣ 3♣] [9♠ 8♥ 6♦ 3♥]
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♣] [6♠ 3♣ 3♥ 2♥]
Result:   Player 1 wins with Four of a Kind, Threes, kicker Nine
------ 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♣] [J♦ T♥ 4♣ 4♥]
Player 2: [J♠ 3♣ 8♥ 2♠] Pair, Jacks, kickers King, Queen, Eight [J♣ J♠ K♣ Q♣ 8♥] [T♥ 4♥ 3♣ 2♠]
Player 3: [3♠ T♠ 2♣ Q♦] Two Pair, Queens over Tens, kicker King [Q♣ Q♦ T♥ T♠ K♣] [J♣ 4♥ 3♠ 2♣]
Player 4: [5♣ 5♥ T♦ 2♦] Pair, Tens, kickers King, Queen, Five [T♦ T♥ K♣ Q♣ 5♣] [J♣ 5♥ 4♥ 2♦]
Player 5: [7♠ 3♥ 6♠ A♣] Ace-high, kickers King, Queen, Jack, Seven [A♣ K♣ Q♣ J♣ 7♠] [T♥ 6♠ 4♥ 3♥]
Player 6: [4♠ 8♦ K♦ T♣] Two Pair, Kings over Tens, kicker Queen [K♣ K♦ T♣ T♥ Q♣] [J♣ 8♦ 4♥ 4♠]
Result:   Player 1 wins with Two Pair, Kings over Queens, kicker Jack
------ Omaha 4 ------
Board:    [2♦ 6♦ 6♣ Q♣ 7♣]
Player 1: [6♠ K♥ A♣ 8♣] Flush, Ace-high, kickers Queen, Eight, Seven, Six [A♣ Q♣ 8♣ 7♣ 6♣] [K♥ 6♦ 6♠ 2♦]
Player 2: [Q♥ 4♥ J♣ 5♥] Two Pair, Queens over Sixes, kicker Jack [Q♣ Q♥ 6♣ 6♦ J♣] [7♣ 5♥ 4♥ 2♦]
Player 3: [2♣ 6♥ 5♣ Q♠] Full House, Sixes full of Queens [6♣ 6♦ 6♥ Q♣ Q♠] [7♣ 5♣ 2♣ 2♦]
Player 4: [9♠ J♥ K♠ J♠] Two Pair, Jacks over Sixes, kicker Queen [J♥ J♠ 6♣ 6♦ Q♣] [K♠ 9♠ 7♣ 2♦]
Player 5: [3♦ 4♦ K♣ 8♦] Pair, Sixes, kickers King, Queen, Eight [6♣ 6♦ K♣ Q♣ 8♦] [7♣ 4♦ 3♦ 2♦]
Player 6: [T♣ Q♦ A♠ 7♥] Two Pair, Queens over Sevens, kicker Six [Q♣ Q♦ 7♣ 7♥ 6♦] [A♠ T♣ 6♣ 2♦]
Result:   Player 3 wins with Full House, Sixes full of Queens
------ 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♣] [J♣ 9♦ 6♦ 3♦]
Player 2: [T♥ J♠ K♠ 2♣] Pair, Kings, kickers Jack, Nine, Six [K♣ K♠ J♠ 9♦ 6♦] [T♥ 5♠ 4♣ 2♣]
Player 3: [A♣ 9♠ T♠ 3♠] Pair, Nines, kickers Ace, King, Six [9♦ 9♠ A♣ K♣ 6♦] [T♠ 5♠ 4♣ 3♠]
Player 4: [7♦ 3♣ 8♠ 7♣] Straight, Nine-high [9♦ 8♠ 7♦ 6♦ 5♠] [K♣ 7♣ 4♣ 3♣]
Player 5: [5♣ Q♠ J♥ 2♠] Pair, Fives, kickers King, Queen, Nine [5♣ 5♠ K♣ Q♠ 9♦] [J♥ 6♦ 4♣ 2♠]
Player 6: [6♠ 7♠ 7♥ 2♥] Pair, Sevens, kickers King, Nine, Six [7♥ 7♠ K♣ 9♦ 6♦] [6♠ 5♠ 4♣ 2♥]
Result:   Player 4 wins with Straight, Nine-high
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
		r := rand.New(rand.NewSource(game.seed))
		pockets, board := cardrank.OmahaHiLo.Deal(r, 1, game.players)
		evs := cardrank.OmahaHiLo.EvalPockets(pockets, board)
		fmt.Printf("------ OmahaHiLo %d ------\n", i+1)
		fmt.Printf("Board: %b\n", board)
		for j := 0; j < game.players; j++ {
			hi, lo := evs[j].Desc(false), evs[j].Desc(true)
			fmt.Printf("Player %d: %b\n", j+1, pockets[j])
			fmt.Printf("  Hi: %s %b %b\n", hi, hi.Best, hi.Unused)
			fmt.Printf("  Lo: %s %b %b\n", lo, lo.Best, lo.Unused)
		}
		hiOrder, hiPivot := cardrank.Order(evs, false)
		loOrder, loPivot := cardrank.Order(evs, true)
		typ := "wins"
		if loPivot == 0 {
			typ = "scoops"
		}
		desc := evs[hiOrder[0]].Desc(false)
		if hiPivot == 1 {
			fmt.Printf("Result (Hi): Player %d %s with %s\n", hiOrder[0]+1, typ, desc)
		} else {
			var s []string
			for j := 0; j < hiPivot; j++ {
				s = append(s, strconv.Itoa(hiOrder[j]+1))
			}
			fmt.Printf("Result (Hi): Players %s push with %s\n", strings.Join(s, ", "), desc)
		}
		if loPivot == 1 {
			desc := evs[loOrder[0]].Desc(true)
			fmt.Printf("Result (Lo): Player %d wins with %s\n", loOrder[0]+1, desc)
		} else if loPivot > 1 {
			var s []string
			for j := 0; j < loPivot; j++ {
				s = append(s, strconv.Itoa(loOrder[j]+1))
			}
			desc := evs[loOrder[0]].Desc(true)
			fmt.Printf("Result (Lo): Players %s push with %s\n", strings.Join(s, ", "), desc)
		} else {
			fmt.Printf("Result (Lo): no player made a lo\n")
		}
	}
}
Output:

------ OmahaHiLo 1 ------
Board: [3♥ 5♥ 4♥ 7♥ K♣]
Player 1: [K♥ J♣ A♥ Q♠]
  Hi: Flush, Ace-high, kickers King, Seven, Five, Four [A♥ K♥ 7♥ 5♥ 4♥] [K♣ Q♠ J♣ 3♥]
  Lo: None [] []
Player 2: [7♣ 4♣ 5♠ 2♠]
  Hi: Two Pair, Sevens over Fives, kicker King [7♣ 7♥ 5♥ 5♠ K♣] [4♣ 4♥ 3♥ 2♠]
  Lo: Seven, Five, Four, Three, Two-low [7♣ 5♥ 4♥ 3♥ 2♠] [K♣ 7♥ 5♠ 4♣]
Result (Hi): Player 1 wins with Flush, Ace-high, kickers King, Seven, Five, Four
Result (Lo): Player 2 wins with Seven, Five, Four, Three, Two-low
------ 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♠] [Q♠ T♠ 9♣ 7♣]
  Lo: None [] []
Player 2: [6♦ Q♣ 8♥ 6♣]
  Hi: Flush, Queen-high, kickers Nine, Seven, Six, Three [Q♣ 9♣ 7♣ 6♣ 3♣] [9♠ 8♥ 6♦ 3♥]
  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♣] [6♠ 3♣ 3♥ 2♥]
  Lo: None [] []
Result (Hi): Player 1 scoops with Four of a Kind, Threes, kicker Nine
Result (Lo): no player made a lo
------ 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♣] [J♦ T♥ 4♣ 4♥]
  Lo: None [] []
Player 2: [J♠ 3♣ 8♥ 2♠]
  Hi: Pair, Jacks, kickers King, Queen, Eight [J♣ J♠ K♣ Q♣ 8♥] [T♥ 4♥ 3♣ 2♠]
  Lo: None [] []
Player 3: [3♠ T♠ 2♣ Q♦]
  Hi: Two Pair, Queens over Tens, kicker King [Q♣ Q♦ T♥ T♠ K♣] [J♣ 4♥ 3♠ 2♣]
  Lo: None [] []
Player 4: [5♣ 5♥ T♦ 2♦]
  Hi: Pair, Tens, kickers King, Queen, Five [T♦ T♥ K♣ Q♣ 5♣] [J♣ 5♥ 4♥ 2♦]
  Lo: None [] []
Player 5: [7♠ 3♥ 6♠ A♣]
  Hi: Ace-high, kickers King, Queen, Jack, Seven [A♣ K♣ Q♣ J♣ 7♠] [T♥ 6♠ 4♥ 3♥]
  Lo: None [] []
Player 6: [4♠ 8♦ K♦ T♣]
  Hi: Two Pair, Kings over Tens, kicker Queen [K♣ K♦ T♣ T♥ Q♣] [J♣ 8♦ 4♥ 4♠]
  Lo: None [] []
Result (Hi): Player 1 scoops with Two Pair, Kings over Queens, kicker Jack
Result (Lo): no player made a lo
------ OmahaHiLo 4 ------
Board: [2♦ 6♦ 6♣ Q♣ 7♣]
Player 1: [6♠ K♥ A♣ 8♣]
  Hi: Flush, Ace-high, kickers Queen, Eight, Seven, Six [A♣ Q♣ 8♣ 7♣ 6♣] [K♥ 6♦ 6♠ 2♦]
  Lo: Eight, Seven, Six, Two, Ace-low [8♣ 7♣ 6♦ 2♦ A♣] [K♥ Q♣ 6♣ 6♠]
Player 2: [Q♥ 4♥ J♣ 5♥]
  Hi: Two Pair, Queens over Sixes, kicker Jack [Q♣ Q♥ 6♣ 6♦ J♣] [7♣ 5♥ 4♥ 2♦]
  Lo: Seven, Six, Five, Four, Two-low [7♣ 6♦ 5♥ 4♥ 2♦] [Q♣ Q♥ J♣ 6♣]
Player 3: [2♣ 6♥ 5♣ Q♠]
  Hi: Full House, Sixes full of Queens [6♣ 6♦ 6♥ Q♣ Q♠] [7♣ 5♣ 2♣ 2♦]
  Lo: None [] []
Player 4: [9♠ J♥ K♠ J♠]
  Hi: Two Pair, Jacks over Sixes, kicker Queen [J♥ J♠ 6♣ 6♦ Q♣] [K♠ 9♠ 7♣ 2♦]
  Lo: None [] []
Player 5: [3♦ 4♦ K♣ 8♦]
  Hi: Pair, Sixes, kickers King, Queen, Eight [6♣ 6♦ K♣ Q♣ 8♦] [7♣ 4♦ 3♦ 2♦]
  Lo: Seven, Six, Four, Three, Two-low [7♣ 6♦ 4♦ 3♦ 2♦] [K♣ Q♣ 8♦ 6♣]
Player 6: [T♣ Q♦ A♠ 7♥]
  Hi: Two Pair, Queens over Sevens, kicker Six [Q♣ Q♦ 7♣ 7♥ 6♦] [A♠ T♣ 6♣ 2♦]
  Lo: None [] []
Result (Hi): Player 3 wins with Full House, Sixes full of Queens
Result (Lo): Player 5 wins with Seven, Six, Four, Three, Two-low
------ 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♣] [J♣ 9♦ 6♦ 3♦]
  Lo: None [] []
Player 2: [T♥ J♠ K♠ 2♣]
  Hi: Pair, Kings, kickers Jack, Nine, Six [K♣ K♠ J♠ 9♦ 6♦] [T♥ 5♠ 4♣ 2♣]
  Lo: None [] []
Player 3: [A♣ 9♠ T♠ 3♠]
  Hi: Pair, Nines, kickers Ace, King, Six [9♦ 9♠ A♣ K♣ 6♦] [T♠ 5♠ 4♣ 3♠]
  Lo: Six, Five, Four, Three, Ace-low [6♦ 5♠ 4♣ 3♠ A♣] [K♣ T♠ 9♦ 9♠]
Player 4: [7♦ 3♣ 8♠ 7♣]
  Hi: Straight, Nine-high [9♦ 8♠ 7♦ 6♦ 5♠] [K♣ 7♣ 4♣ 3♣]
  Lo: Seven, Six, Five, Four, Three-low [7♦ 6♦ 5♠ 4♣ 3♣] [K♣ 9♦ 8♠ 7♣]
Player 5: [5♣ Q♠ J♥ 2♠]
  Hi: Pair, Fives, kickers King, Queen, Nine [5♣ 5♠ K♣ Q♠ 9♦] [J♥ 6♦ 4♣ 2♠]
  Lo: None [] []
Player 6: [6♠ 7♠ 7♥ 2♥]
  Hi: Pair, Sevens, kickers King, Nine, Six [7♥ 7♠ K♣ 9♦ 6♦] [6♠ 5♠ 4♣ 2♥]
  Lo: Seven, Six, Five, Four, Two-low [7♠ 6♦ 5♠ 4♣ 2♥] [K♣ 9♦ 7♥ 6♠]
Result (Hi): Player 4 wins with Straight, Nine-high
Result (Lo): Player 3 wins with Six, Five, Four, Three, Ace-low
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
		r := rand.New(rand.NewSource(game.seed))
		pockets, _ := cardrank.Razz.Deal(r, 1, game.players)
		evs := cardrank.Razz.EvalPockets(pockets, nil)
		fmt.Printf("------ Razz %d ------\n", i+1)
		for j := 0; j < game.players; j++ {
			desc := evs[j].Desc(false)
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, pockets[j], desc, desc.Best, desc.Unused)
		}
		order, pivot := cardrank.Order(evs, false)
		desc := evs[order[0]].Desc(false)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s\n", order[0]+1, desc)
		} else {
			var s []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(order[j]+1))
			}
			fmt.Printf("Result:   Players %s push with %s\n", strings.Join(s, ", "), desc)
		}
	}
}
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♠] [7♥ 4♥]
Result:   Player 2 wins with Seven, Five, Four, Three, Two-low
------ Razz 2 ------
Player 1: [3♠ 3♦ T♠ Q♠ T♥ 9♠ K♥] King, Queen, Ten, Nine, Three-low [K♥ Q♠ T♠ 9♠ 3♠] [T♥ 3♦]
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♥] [K♠ Q♦]
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♦] [Q♥ J♦]
Result:   Player 5 wins with Seven, Six, Five, Two, Ace-low
------ Razz 3 ------
Player 1: [K♠ Q♠ 4♣ J♦ 7♥ 7♣ J♥] King, Queen, Jack, Seven, Four-low [K♠ Q♠ J♦ 7♥ 4♣] [J♥ 7♣]
Player 2: [J♠ 3♣ 8♥ 2♠ J♣ Q♣ 7♦] Jack, Eight, Seven, Three, Two-low [J♠ 8♥ 7♦ 3♣ 2♠] [Q♣ J♣]
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♣] [A♦ 6♦]
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
------ Razz 4 ------
Player 1: [6♠ K♥ A♣ 8♣ 2♠ 5♦ A♥] Eight, Six, Five, Two, Ace-low [8♣ 6♠ 5♦ 2♠ A♣] [A♥ K♥]
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♣] [K♦ J♠]
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
------ Razz 5 ------
Player 1: [3♦ 4♦ 5♦ J♣ 4♥ K♥ 8♣] Jack, Eight, Five, Four, Three-low [J♣ 8♣ 5♦ 4♦ 3♦] [K♥ 4♥]
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♣] [A♥ K♣]
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♥] [K♦ 7♥]
Result:   Player 5 wins with Eight, Five, Four, Two, Ace-low
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
		r := rand.New(rand.NewSource(game.seed))
		pockets, board := cardrank.Royal.Deal(r, 1, game.players)
		evs := cardrank.Royal.EvalPockets(pockets, board)
		fmt.Printf("------ Royal %d ------\n", i+1)
		fmt.Printf("Board:    %b\n", board)
		for j := 0; j < game.players; j++ {
			desc := evs[j].Desc(false)
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, pockets[j], desc, desc.Best, desc.Unused)
		}
		order, pivot := cardrank.Order(evs, false)
		desc := evs[order[0]].Desc(false)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s\n", order[0]+1, desc)
		} else {
			var s []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(order[j]+1))
			}
			fmt.Printf("Result:   Players %s push with %s\n", strings.Join(s, ", "), desc)
		}
	}
}
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
------ 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
------ 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
------ 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
------ 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
------ 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
------ 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
------ 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
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
		r := rand.New(rand.NewSource(game.seed))
		pockets, board := cardrank.Short.Deal(r, 1, game.players)
		evs := cardrank.Short.EvalPockets(pockets, board)
		fmt.Printf("------ Short %d ------\n", i+1)
		fmt.Printf("Board:    %b\n", board)
		for j := 0; j < game.players; j++ {
			desc := evs[j].Desc(false)
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, pockets[j], desc, desc.Best, desc.Unused)
		}
		order, pivot := cardrank.Order(evs, false)
		desc := evs[order[0]].Desc(false)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s\n", order[0]+1, desc)
		} else {
			var s []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(order[j]+1))
			}
			fmt.Printf("Result:   Players %s push with %s\n", strings.Join(s, ", "), desc)
		}
	}
}
Output:

------ Short 1 ------
Board:    [9♥ A♦ A♥ 8♣ A♣]
Player 1: [8♥ A♠] Four of a Kind, Aces, kicker Nine [A♣ A♦ A♥ A♠ 9♥] [8♣ 8♥]
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 Nine
------ 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
------ 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
------ 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, Silver Tongue [Q♦ J♦ T♦ 9♦ 8♦] [9♣ 6♣]
Player 4: [A♣ A♦] Flush, Ace-high, kickers Queen, Ten, Nine, Eight [A♦ Q♦ T♦ 9♦ 8♦] [A♣ 9♣]
Result:   Player 3 wins with Straight Flush, Queen-high, Silver Tongue
------ 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
------ 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
------ 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
------ 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
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
		r := rand.New(rand.NewSource(game.seed))
		pockets, _ := cardrank.Stud.Deal(r, 1, game.players)
		evs := cardrank.Stud.EvalPockets(pockets, nil)
		fmt.Printf("------ Stud %d ------\n", i+1)
		for j := 0; j < game.players; j++ {
			desc := evs[j].Desc(false)
			fmt.Printf("Player %d: %b %s %b %b\n", j+1, pockets[j], desc, desc.Best, desc.Unused)
		}
		order, pivot := cardrank.Order(evs, false)
		desc := evs[order[0]].Desc(false)
		if pivot == 1 {
			fmt.Printf("Result:   Player %d wins with %s\n", order[0]+1, desc)
		} else {
			var s []string
			for j := 0; j < pivot; j++ {
				s = append(s, strconv.Itoa(order[j]+1))
			}
			fmt.Printf("Result:   Players %s push with %s\n", strings.Join(s, ", "), desc)
		}
	}
}
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
------ 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♣] Ace-high, kickers King, Queen, Nine, Eight [A♥ K♠ Q♦ 9♣ 8♣] [7♣ 2♣]
Player 4: [K♦ T♦ 8♦ 4♥ 3♣ J♠ 2♦] King-high, kickers Jack, Ten, Eight, Four [K♦ J♠ T♦ 8♦ 4♥] [3♣ 2♦]
Player 5: [J♦ 2♥ Q♥ 6♠ 5♦ 7♠ A♦] 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
------ 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
------ 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♠] 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
------ 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♠] 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
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
		r := rand.New(rand.NewSource(game.seed))
		pockets, _ := cardrank.StudHiLo.Deal(r, 1, game.players)
		evs := cardrank.StudHiLo.EvalPockets(pockets, nil)
		fmt.Printf("------ StudHiLo %d ------\n", i+1)
		for j := 0; j < game.players; j++ {
			hi, lo := evs[j].Desc(false), evs[j].Desc(true)
			fmt.Printf("Player %d: %b\n", j+1, pockets[j])
			fmt.Printf("  Hi: %s %b %b\n", hi, hi.Best, hi.Unused)
			fmt.Printf("  Lo: %s %b %b\n", lo, lo.Best, lo.Unused)
		}
		hiOrder, hiPivot := cardrank.Order(evs, false)
		loOrder, loPivot := cardrank.Order(evs, true)
		typ := "wins"
		if loPivot == 0 {
			typ = "scoops"
		}
		desc := evs[hiOrder[0]].Desc(false)
		if hiPivot == 1 {
			fmt.Printf("Result (Hi): Player %d %s with %s\n", hiOrder[0]+1, typ, desc)
		} else {
			var s []string
			for j := 0; j < hiPivot; j++ {
				s = append(s, strconv.Itoa(hiOrder[j]+1))
			}
			fmt.Printf("Result (Hi): Players %s push with %s\n", strings.Join(s, ", "), desc)
		}
		if loPivot == 1 {
			desc := evs[loOrder[0]].Desc(true)
			fmt.Printf("Result (Lo): Player %d wins with %s\n", loOrder[0]+1, desc)
		} else if loPivot > 1 {
			var s []string
			for j := 0; j < loPivot; j++ {
				s = append(s, strconv.Itoa(loOrder[j]+1))
			}
			desc := evs[loOrder[0]].Desc(true)
			fmt.Printf("Result (Lo): Players %s push with %s\n", strings.Join(s, ", "), desc)
		} else {
			fmt.Printf("Result (Lo): no player made a lo\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♠] [7♥ 4♥]
Result (Hi): Player 2 wins with Two Pair, Sevens over Fours, kicker Five
Result (Lo): Player 2 wins with Seven, Five, Four, Three, Two-low
------ 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: 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: 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: 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♦] [Q♥ J♦]
Result (Hi): Player 1 wins with Two Pair, Tens over Threes, kicker King
Result (Lo): Player 5 wins with Seven, Six, Five, Two, Ace-low
------ 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♣] [A♦ 6♦]
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
Result (Lo): Player 5 wins with Eight, Seven, Six, Three, Ace-low
------ 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♣] [A♥ K♥]
Player 2: [Q♥ 4♥ J♣ 5♥ 2♦ 7♣ 3♠]
  Hi: 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
Result (Lo): Player 2 wins with Seven, Five, Four, Three, Two-low
------ 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: 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
Result (Lo): Player 5 wins with Eight, Five, Four, Two, Ace-low
const (
	Holdem         Type = 'H'<<8 | 'h' // Hh
	Split          Type = 'H'<<8 | 'l' // Hl
	Short          Type = 'H'<<8 | 's' // Hs
	Manila         Type = 'H'<<8 | 'm' // Hm
	Spanish        Type = 'H'<<8 | 'p' // Hp
	Royal          Type = 'H'<<8 | 'r' // Hr
	Double         Type = 'H'<<8 | 'd' // Hd
	Showtime       Type = 'H'<<8 | 't' // Ht
	Swap           Type = 'H'<<8 | 'w' // Hw
	River          Type = 'H'<<8 | 'v' // Hv
	Dallas         Type = 'H'<<8 | 'a' // Ha
	Houston        Type = 'H'<<8 | 'u' // Hu
	Draw           Type = 'D'<<8 | 'h' // Dh
	DrawHiLo       Type = 'D'<<8 | 'l' // Dl
	Stud           Type = 'S'<<8 | 'h' // Sh
	StudHiLo       Type = 'S'<<8 | 'l' // Sl
	StudFive       Type = 'S'<<8 | '5' // S5
	Video          Type = 'J'<<8 | 'h' // Jh
	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
	OmahaRoyal     Type = 'O'<<8 | 'r' // Or
	Courchevel     Type = 'O'<<8 | 'c' // Oc
	CourchevelHiLo Type = 'O'<<8 | 'e' // Oe
	Fusion         Type = 'O'<<8 | 'f' // Of
	FusionHiLo     Type = 'O'<<8 | 'F' // OF
	Soko           Type = 'K'<<8 | 'h' // Kh
	SokoHiLo       Type = 'K'<<8 | 'l' // Kl
	Lowball        Type = 'L'<<8 | '1' // L1
	LowballTriple  Type = 'L'<<8 | '3' // L3
	Razz           Type = 'R'<<8 | 'a' // Ra
	Badugi         Type = 'B'<<8 | 'a' // Ba
	Kuhn           Type = 'K'<<8 | 'u' // Ku
	Leduc          Type = 'L'<<8 | 'e' // Le
	RhodeIsland    Type = 'R'<<8 | 'I' // RI
)

Types.

func IdToType

func IdToType(id string) (Type, error)

IdToType converts id to a type.

func Types

func Types() []Type

Types returns registered types.

func (Type) Blinds

func (typ Type) Blinds() []string

Blinds returns the type's blind names.

func (Type) Board

func (typ Type) Board() int

Board returns the type's total dealt board cards.

func (Type) BoardDiscard

func (typ Type) BoardDiscard() int

BoardDiscard returns the type's total board discard.

func (Type) Cactus

func (typ Type) Cactus() bool

Cactus returns true when the type's eval is a Cactus eval.

func (Type) Deal

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

Deal creates a new dealer for the type, shuffling the deck by shuffles, returning the specified pocket count and Hi board.

func (Type) Dealer

func (typ Type) Dealer(shuffler Shuffler, shuffles, count int) *Dealer

Dealer creates a new dealer with a deck shuffled by shuffles, with specified pocket count.

func (Type) Deck

func (typ Type) Deck() *Deck

Deck returns a new deck for the type.

func (Type) DeckType

func (typ Type) DeckType() DeckType

DeckType returns the type's deck type.

func (Type) Desc

func (typ Type) Desc() TypeDesc

Desc returns the type description.

func (Type) Double

func (typ Type) Double() bool

Double returns true when the type has double boards.

func (Type) Draw

func (typ Type) Draw() bool

Draw returns true when one or more streets allows draws.

func (Type) Eval

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

Eval creates a new eval for the type, evaluating the pocket and board.

func (Type) EvalPockets

func (typ Type) EvalPockets(pockets [][]Card, board []Card) []*Eval

EvalPockets creates new evals for the type, evaluating each of the pockets and board.

func (Type) ExpValue

func (typ Type) ExpValue(ctx context.Context, pocket []Card, opts ...CalcOption) (*ExpValue, bool)

ExpValue calculates expected value for a single pocket. Use WithBoard to pass a board.

func (Type) Format

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

Format satisfies the fmt.Formatter interface.

func (Type) Id

func (typ Type) Id() string

Id returns the type's id.

func (Type) Low

func (typ Type) Low() bool

Low returns true when the type supports 8-or-better lo eval.

func (Type) MarshalText

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

MarshalText satisfies the encoding.TextMarshaler interface.

func (Type) Max

func (typ Type) Max() int

Max returns the type's max players.

func (Type) Name

func (typ Type) Name() string

Name returns the type name.

func (Type) Odds

func (typ Type) Odds(ctx context.Context, pockets [][]Card, board []Card, opts ...CalcOption) (*Odds, *Odds, bool)

Odds calculates the odds for the pockets, board.

func (Type) Once

func (typ Type) Once() bool

Once returns true when draws are limited to one time.

func (Type) Pocket

func (typ Type) Pocket() int

Pocket returns the type's total dealt pocket cards.

func (Type) PocketDiscard

func (typ Type) PocketDiscard() int

PocketDiscard returns the type's total pocket discard.

func (Type) Show

func (typ Type) Show() bool

Show returns true when the type shows folded cards.

func (Type) Streets

func (typ Type) Streets() []StreetDesc

Streets returns the type's street descriptions.

func (*Type) UnmarshalText

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

UnmarshalText satisfies the encoding.TextUnmarshaler interface.

type TypeDesc

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 the enabling the Hi/Lo variant, with an 8-or-better
	// evaluated Lo.
	Low bool
	// Double is true when there are double community boards where the first
	// and second board is evaluated as the Hi and Lo, respectively.
	Double bool
	// Show is true when folded cards are shown.
	Show bool
	// Once is true when a draw can only occur once.
	Once bool
	// Blinds are the blind names.
	Blinds []string
	// Streets are the betting streets.
	Streets []StreetDesc
	// Deck is the deck type.
	Deck DeckType
	// Eval is the eval type.
	Eval EvalType
	// HiDesc is the Hi description type.
	HiDesc DescType
	// LoDesc is the Lo description type.
	LoDesc DescType
	// contains filtered or unexported fields
}

TypeDesc is a type description.

func DefaultTypes

func DefaultTypes() []TypeDesc

DefaultTypes returns the default type descriptions. The returned TypeDesc's will be automatically registered, unless using the noinit tag.

func NewType

func NewType(id string, typ Type, name string, opts ...TypeOption) (*TypeDesc, error)

NewType creates a new type description. Created type descriptions must be registered with RegisterType before being used for eval.

func (*TypeDesc) Apply

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

Apply applies street options.

type TypeOption

type TypeOption func(*TypeDesc)

TypeOption is a type description option.

func WithBadugi

func WithBadugi(opts ...StreetOption) TypeOption

WithBadugi is a type description option to set Badugi definitions.

func WithCourchevel

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

WithCourchevel is a type description option to set Courchevel definitions.

func WithDallas

func WithDallas(low bool, opts ...StreetOption) TypeOption

WithDallas is a type description option to set Dallas definitions.

func WithDouble

func WithDouble(opts ...StreetOption) TypeOption

WithDouble is a type description option to set Double definitions.

func WithDraw

func WithDraw(low bool, opts ...StreetOption) TypeOption

WithDraw is a type description option to set Draw definitions.

func WithFusion

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

WithFusion is a type description option to set Fusion definitions.

func WithHoldem

func WithHoldem(low bool, opts ...StreetOption) TypeOption

WithHoldem is a type description option to set Holdem definitions.

func WithHouston

func WithHouston(low bool, opts ...StreetOption) TypeOption

WithHouston is a type description option to set Houston definitions.

func WithKuhn

func WithKuhn(opts ...StreetOption) TypeOption

WithKuhn is a type description option to set Kuhn definitions.

func WithLeduc

func WithLeduc(opts ...StreetOption) TypeOption

WithLeduc is a type description option to set Leduc definitions.

func WithLowball

func WithLowball(multi bool, opts ...StreetOption) TypeOption

WithLowball is a type description option to set Lowball definitions.

func WithManila

func WithManila(opts ...StreetOption) TypeOption

WithManila is a type description option to set Manila definitions.

func WithOmaha

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

WithOmaha is a type description option to set Omaha definitions.

func WithOmahaDouble

func WithOmahaDouble(opts ...StreetOption) TypeOption

WithOmahaDouble is a type description option to set OmahaDouble definitions.

func WithOmahaFive

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

WithOmahaFive is a type description option to set OmahaFive definitions.

func WithOmahaRoyal

func WithOmahaRoyal(opts ...StreetOption) TypeOption

WithOmahaRoyal is a type description option to set OmahaRoyal definitions.

func WithOmahaSix

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

WithOmahaSix is a type description option to set OmahaSix definitions.

func WithRazz

func WithRazz(opts ...StreetOption) TypeOption

WithRazz is a type description option to set Razz definitions.

func WithRhodeIsland

func WithRhodeIsland(opts ...StreetOption) TypeOption

WithRhodeIsland is a type description option to set RhodeIsland definitions.

func WithRiver

func WithRiver(low bool, opts ...StreetOption) TypeOption

WithRiver is a type description option to set River definitions.

func WithRoyal

func WithRoyal(opts ...StreetOption) TypeOption

WithRoyal is a type description option to set Royal definitions.

func WithShort

func WithShort(opts ...StreetOption) TypeOption

WithShort is a type description option to set Short definitions.

func WithShowtime

func WithShowtime(low bool, opts ...StreetOption) TypeOption

WithShowtime is a type description option to set Showtime definitions.

func WithSoko

func WithSoko(low bool, opts ...StreetOption) TypeOption

WithSoko is a type description option to set Soko definitions.

func WithSpanish

func WithSpanish(opts ...StreetOption) TypeOption

WithSpanish is a type description option to set Spanish definitions.

func WithStud

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

WithStud is a type description option to set Stud definitions.

func WithStudFive

func WithStudFive(low bool, opts ...StreetOption) TypeOption

WithStudFive is a type description option to set StudFive definitions.

func WithSwap

func WithSwap(low bool, opts ...StreetOption) TypeOption

WithSwap is a type description option to set Swap definitions.

func WithVideo

func WithVideo(low bool, opts ...StreetOption) TypeOption

WithVideo is a type description option to set Video definitions.

type Win

type Win struct {
	Evals []*Eval
	Order []int
	Pivot int
	Low   bool
	Scoop bool
	Names []string
}

Win formats win information.

func NewWin

func NewWin(evs []*Eval, order []int, pivot int, low, scoop bool, names []string) *Win

NewWin creates a new win.

func (*Win) Desc

func (win *Win) Desc() []*EvalDesc

Desc returns the eval descriptions.

func (*Win) Format

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

Format satisfies the fmt.Formatter interface.

func (*Win) Invalid

func (win *Win) Invalid() bool

Invalid returns true when there are no valid winners.

func (*Win) Verb

func (win *Win) Verb() string

Verb returns the win verb.

Directories

Path Synopsis
_example
Package paycalc contains a tournament payout tables.
Package paycalc contains a tournament payout tables.

Jump to

Keyboard shortcuts

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