poker-calculations
v3.0.0
Published
NL Hold'em library for Node: hand evaluation, Monte Carlo and exact equity, decideAction, range tools, board texture, chip/pot/rake math, ICM, side pots, opponent modeling, statistics, and more - C++20 core with prebuilt N-API binaries.
Maintainers
Readme
Poker-Calculations is a production-ready Node library for NL Hold’em: fast hand evaluation, Monte Carlo and exact equity, pot odds and chip EV, ICM and side pots, draw probabilities, GTO-style frequencies, fold-equity models, Kelly and jam analysis, and a rule-based decideAction layer over serialized table state. Everything runs in native code and ships with prebuilt binaries—npm install does not require CMake, a compiler, or the Windows SDK.
What you can build
- Equity calculators and training tools with reproducible Monte Carlo seeds
- Simulators and bots tuned via
BotConfigand optional opponent models - Tournament tools with Harville ICM, bubble factors, and layered side-pot EV
- Analysis backends (wrap the library yourself—there are no built-in HTTP endpoints)
Highlights
| | |
| --- | --- |
| Hands & equity | Best-five evaluation, parallel MC simulation, exact HU equity vs a random hand, draw and runner-runner probabilities |
| Table math | SPR, pot odds, rake-aware call EV, breakeven equity, Harrington M / Q, sizing and commitment |
| Strategy | decideAction from serialized state using MC equity, pot odds, call EV, legal-action summaries, and diagnostics |
| Tournaments | ICM (Harville and Weitzman chip utility), placement and payout expectations, pairwise bubble factor, side-pot ladders |
| Theory helpers | MDF / alpha, fold-equity breakevens, Kelly and Chubukov symmetric-jam search, Wilson and Agresti–Coull intervals, risk-of-ruin approximations |
| Tournament & runouts | Shapley ICM, runout equity spread, range materialization, subgame bet toys — guide |
| Ranges & boards | Range algebra, range distances, notation buckets, board texture, scare cards, and range-board coverage |
| Opponent modeling | Fold-to-c-bet posteriors, aggression/showdown tendency estimates, range elasticity, and exploit adjustments |
| Developer experience | index.d.ts typings, 300 native exports, docs at poker-calculations.devomb.com |
Published releases include N-API prebuilds for Linux (glibc and musl), macOS, and Windows via node-gyp-build. Linux glibc builds use static libstdc++/libgcc where needed so older server and serverless images avoid GLIBCXX_* mismatches.
Install
Node.js 18+
npm install poker-calculationsQuick start
Cards use strings like "Ah" and "Td" (ten may be "10h"), or packed Uint8Array deck ids (0..51) for hot paths — see encode.js and Packed card input on the docs site.
CommonJS
const poker = require('poker-calculations');
poker.evaluateBestHand(['Ah', 'Ac', 'Kd', 'Ks', 'Qh', 'Jh', 'Th']);
// → { rank, rankCategory, strength, kickers }
poker.parseCompactCardList('AhKhQh', { outFormat: 'packed' }); // Uint8Array for hot paths
poker.evaluateBestHand(['Ah', 'Ac', 'Kd', 'Ks', 'Qh'], { format: 'slim' });
// → { rankCategory, strength } only
const equity = poker.simulateHandOutcome(
['Ah', 'Kh'],
['Qh', 'Jh', 'Th'],
10_000,
42,
1
);
// Non-blocking (libuv thread pool) — same args as sync; returns a Promise
const equityAsync = await poker.simulateHandOutcomeAsync(
['Ah', 'Kh'],
['Qh', 'Jh', 'Th'],
10_000,
42,
1
);
// Optional AbortSignal (cooperative cancel; rejects with AbortError)
const ac = new AbortController();
const equityCancellable = await poker.simulateHandOutcomeAsync(
['Ah', 'Kh'],
['Qh', 'Jh', 'Th'],
10_000,
42,
1,
{ signal: ac.signal }
);
const spr = poker.spr(90, 270);
const mdf = poker.minimumDefenseFrequency(100, 50);ESM
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const poker = require('poker-calculations');Walkthroughs, guides, and the full API live on the docs site: introduction · API reference.
Optional subpath: poker-calculations/encode
Six pure-JS helpers for deck ids and PKST bytes (no extra native exports):
const encode = require('poker-calculations/encode');
encode.packCards(['Ah', 'Kh']);
encode.packPokerState(nativePokerState);See Packed card input and Packed poker state on the docs site.
API at a glance
All exports come from the native addon. Grouped overview—see the reference for signatures and examples.
| Area | Examples |
| --- | --- |
| Hands & equity | evaluateBestHand, evaluateHandStrength, evaluateHandStrengthFast, simulateHandOutcome, simulateHandOutcomeAsync, parallelHandSimulation, exactHuEquityVsRandomHand, … |
| Strategy | decideAction, decideActionAsync, legalActionSummary, decideActionWithDiagnostics |
| Pot / EV | potOddsRatio, expectedValueCall, breakevenCallEquity, rakeFromPot |
| Stacks & display | spr, harringtonM, harringtonQ, stackInBigBlinds, formatPotOdds |
| Draws & heuristics | ruleOfTwoEquity, hypergeometricOneCardHitProbability, flopToRiverAtLeastOneHitProbability |
| GTO-style | minimumDefenseFrequency, alphaFrequency, bluffToValueRatio |
| Fold equity | breakevenFoldEquityPureBluff, breakevenFoldEquitySemiBluff |
| Range tools | normalizeSparseRange, rangeTopCombos, rangeBucketWeightsByNotation, rangeDistanceJensenShannon |
| Board texture | boardTextureScore, enumerateScareCards, rangeBoardCoverage, heroBoardConnectivityScore |
| Sizing plans | cbetSizeEvGrid, probeBetEvGrid, geometricStreetSizingPlan, thinValueMargin |
| Opponent modeling | opponentFoldToCbetPosterior, opponentAggressionFactor, villainLineRangeShift |
| ICM & side pots | icmExpectedPayouts, icmExpectedPayoutsWeitzman, icmPairwiseBubbleFactor, sidePotLadderFromCommitments |
| Stats & risk | wilsonScoreInterval, riskOfRuinDiffusionApprox, monteCarloStandardError |
| Kelly & jam | kellyCriterionBinary, chubukovSymmetricJamEv, chubukovMaxSymmetricJamStackBinarySearch |
A complete inventory is in FEATURES_ADDED.md.
Bundlers and serverless
Load from runtime code paths (for example a lazy require() inside a route handler) if your bundler or next build evaluates server modules at build time. You still need a prebuild that matches deployment OS and libc (glibc vs musl on Linux).
Responsible use
Use this for simulators, research, and automation you are permitted to run. It is not intended to bypass third-party terms of service on real-money sites.
License
Clone installs without local prebuilds need CMake 3.16+ and a C++ toolchain (MSVC on Windows, Xcode CLI on macOS, GCC on Linux).
npm ci
npm run build:native
node scripts/stage-prebuild.js <platform-arch>Use tuples like win32-x64, linux-x64, darwin-arm64. For Alpine/musl: node scripts/stage-prebuild.js linux-x64 musl.
Publishing is automated via .github/workflows/npm-publish.yml on main when package.json / package-lock.json change, using npm trusted publishing (OIDC). Bump version on main, keep the lockfile in sync, and let CI build prebuilds and publish when that version is not already on npm.
Trusted publisher settings on npm must match repository.url in package.json and workflow filename npm-publish.yml. Manual publish: stage binaries under prebuilds/, then npm publish (or set SKIP_PREBUILD_CHECK=1 only when intentionally publishing without binaries).
Headers under include/poker/. Build the static poker_lib:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build buildWhen built via cmake-js for Node, poker_calculations.node and poker_lib are produced.
Sketch: PokerGameState, GameEngine::apply_action, evaluate_best_hand, simulate_hand_outcome, decide_action, and chip math in poker_math.hpp.
