Navigation Menu

Skip to content

cardrank/cardrank

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

Links

About

Go types, funcs, and utilities for working with cards, decks, and evaluating poker hands (Holdem, Omaha, Stud, more)

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages