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

cardrank.io/cardrank

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

GoDoc Tests on Linux, MacOS and Windows Go Report Card

Overview

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

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

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

Using

See Go documentation.

go get cardrank.io/cardrank

Examples

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

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

Texas Holdem

package main

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

	"cardrank.io/cardrank"
)

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

Output:

------ Holdem 1653086388531833787 ------
Board:    [A♣ 3♥ Q♥ J♣ J♠]
Player 1: [5♣ 5♦] Two Pair, Jacks over Fives, kicker Ace [J♣ J♠ 5♣ 5♦ A♣] [Q♥ 3♥]
Player 2: [A♥ 7♠] Two Pair, Aces over Jacks, kicker Queen [A♣ A♥ J♣ J♠ Q♥] [7♠ 3♥]
Player 3: [8♥ 3♣] Two Pair, Jacks over Threes, kicker Ace [J♣ J♠ 3♣ 3♥ A♣] [Q♥ 8♥]
Player 4: [9♣ T♠] Pair, Jacks, kickers Ace, Queen, Ten [J♣ J♠ A♣ Q♥ T♠] [9♣ 3♥]
Player 5: [6♣ J♥] Three of a Kind, Jacks, kickers Ace, Queen [J♣ J♥ J♠ A♣ Q♥] [6♣ 3♥]
Player 6: [2♣ T♦] Pair, Jacks, kickers Ace, Queen, Ten [J♣ J♠ A♣ Q♥ T♦] [3♥ 2♣]
Result:   Player 5 wins with Three of a Kind, Jacks, kickers Ace, Queen [J♣ J♥ J♠ A♣ Q♥]

Omaha Hi/Lo

package main

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

	"cardrank.io/cardrank"
)

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

Output:

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

Hand Ranking

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

Rankers

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

Default and Hybrid Rankers

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

Ordering and Winner Determination

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

Build Tags

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

portable

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

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

GOOS=js GOARCH=wasm go build -tags portable

embedded

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

GOOS=js GOARCH=wasm go build -tags embedded

noinit

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

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

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

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

See z.go for initialization logic.

Development Status

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

Future

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

Similar Resources

Library for multi-armed bandit selection strategies, including efficient deterministic implementations of Thompson sampling and epsilon-greedy.

Library for multi-armed bandit selection strategies, including efficient deterministic implementations of Thompson sampling and epsilon-greedy.

Mab Multi-Armed Bandits Go Library Description Installation Usage Creating a bandit and selecting arms Numerical integration with numint Documentation

Jan 2, 2023

A program that generates a folder structure with challenges and projects for mastering a programming language.

Challenge Generator A program that generates a folder structure with challenges and projects for mastering a programming language. Explore the docs »

Aug 31, 2022

Gota: DataFrames and data wrangling in Go (Golang)

Gota: DataFrames, Series and Data Wrangling for Go This is an implementation of DataFrames, Series and data wrangling methods for the Go programming l

Jan 5, 2023

An open source embedding vector similarity search engine powered by Faiss, NMSLIB and Annoy

An open source embedding vector similarity search engine powered by Faiss, NMSLIB and Annoy

Click to take a quick look at our demos! Image search Chatbots Chemical structure search Milvus is an open-source vector database built to power AI ap

Jan 7, 2023

Open-source software engineering competency and career plans.

Software Engineering Competency Matrix This repository contains an "Open Competency Matrix" for Software Engineers. It includes a standard data struct

Oct 4, 2022

Example of Neural Network models of social and personality psychology phenomena

SocialNN Example of Neural Network models of social and personality psychology phenomena This repository gathers a collection of neural network models

Dec 5, 2022

Spice.ai is an open source, portable runtime for training and using deep learning on time series data.

Spice.ai is an open source, portable runtime for training and using deep learning on time series data.

Spice.ai Spice.ai is an open source, portable runtime for training and using deep learning on time series data. ⚠️ DEVELOPER PREVIEW ONLY Spice.ai is

Dec 15, 2022

Versioned model registry suitable for temporary in-training storage and permanent storage

Cogment Model Registry Cogment is an innovative open source AI platform designed to leverage the advent of AI to benefit humankind through human-AI co

May 26, 2022

GoPlus - The Go+ language for engineering, STEM education, and data science

The Go+ language for engineering, STEM education, and data science Summary about Go+ What are mainly impressions about Go+? A static typed language. F

Jan 8, 2023
On-line Machine Learning in Go (and so much more)

goml Golang Machine Learning, On The Wire goml is a machine learning library written entirely in Golang which lets the average developer include machi

Jan 5, 2023
The open source, end-to-end computer vision platform. Label, build, train, tune, deploy and automate in a unified platform that runs on any cloud and on-premises.
The open source, end-to-end computer vision platform. Label, build, train, tune, deploy and automate in a unified platform that runs on any cloud and on-premises.

End-to-end computer vision platform Label, build, train, tune, deploy and automate in a unified platform that runs on any cloud and on-premises. onepa

Dec 12, 2022
Genetic Algorithm and Particle Swarm Optimization

evoli Genetic Algorithm and Particle Swarm Optimization written in Go Example Problem Given f(x,y) = cos(x^2 * y^2) * 1/(x^2 * y^2 + 1) Find (x,y) suc

Dec 22, 2022
k-modes and k-prototypes clustering algorithms implementation in Go

go-cluster GO implementation of clustering algorithms: k-modes and k-prototypes. K-modes algorithm is very similar to well-known clustering algorithm

Nov 29, 2022
Probability distributions and associated methods in Go

godist godist provides some Go implementations of useful continuous and discrete probability distributions, as well as some handy methods for working

Sep 27, 2022
Bayesian text classifier with flexible tokenizers and storage backends for Go

Shield is a bayesian text classifier with flexible tokenizer and backend store support Currently implemented: Redis backend English tokenizer Example

Nov 25, 2022
Training materials and labs for a "Getting Started" level course on COBOL

COBOL Programming Course This project is a set of training materials and labs for COBOL on z/OS. The following books are available within this reposit

Dec 30, 2022
A curated list of Awesome Go performance libraries and tools

Awesome Go performance Collection of the Awesome™ Go libraries, tools, project around performance. Contents Algorithm Assembly Benchmarks Compiling Co

Jan 3, 2023
Deploy, manage, and scale machine learning models in production
Deploy, manage, and scale machine learning models in production

Deploy, manage, and scale machine learning models in production. Cortex is a cloud native model serving platform for machine learning engineering teams.

Dec 30, 2022
The Go kernel for Jupyter notebooks and nteract.
The Go kernel for Jupyter notebooks and nteract.

gophernotes - Use Go in Jupyter notebooks and nteract gophernotes is a Go kernel for Jupyter notebooks and nteract. It lets you use Go interactively i

Dec 30, 2022