Give CPUs distinct personalities built on different poker libraries

Each CPU now thinks with one of four engines, each backed by a different
published library (pinned versions):

- montecarlo (@pokertools/evaluator): the existing balanced Monte Carlo
  equity player, moved to server/bots/montecarlo.js.
- calculator (poker-calculations): the library's decideAction over the
  table state; push/fold below 12BB via its jam breakeven equity.
  Skipped automatically if the native addon cannot load.
- range (poker-utils): tight player; preflop by hand-strength percentile,
  postflop equity vs an estimated opponent range, bluffs only when
  alpha/bluffEV say they pay.
- madehand (pokersolver): loose, sticky player that only looks at the
  made hand and draws.

server/ai.js assigns a mix of engines per table (makeStyles), falls back
to the Monte Carlo engine on errors, and legalizes every decision.
The engine and its parameters stay server-side; players cannot tell
which library a CPU uses. Tests cover every engine and the no-leak rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
agomizi1cmandClaude Opus 5.5 committed 2026-10-17 17:51:15 +09:00
1 parent d92953a270
commit 3116b1da9f
11 files changed
+702 -131

No files matched your search

+45 -1
View File
@@ -11,10 +11,13 @@
"@pokertools/engine": "2.1.0",
"@pokertools/evaluator": "2.1.0",
"express": "^4.22.3",
"poker-calculations": "4.0.3",
"poker-utils": "14.0.1",
"pokersolver": "2.1.4",
"socket.io": "^4.8.4"
},
"engines": {
"node": ">=18"
"node": ">=24"
}
},
"node_modules/@pokertools/engine": {
@@ -674,6 +677,17 @@
"node": ">= 0.6"
}
},
"node_modules/node-gyp-build": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
"license": "MIT",
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
"node-gyp-build-test": "build-test.js"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -722,6 +736,36 @@
"integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
"license": "MIT"
},
"node_modules/poker-calculations": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/poker-calculations/-/poker-calculations-4.0.3.tgz",
"integrity": "sha512-vpX+2nVuSGxbVd4+oGrbUSthEQ+/T5sLnkOQsxOB9ir7SAl0vcb9XCDWgjXUsFBHXR+h+MQCK2TIrfWaj+SyhA==",
"license": "ISC",
"dependencies": {
"node-gyp-build": "^4.8.4"
},
"engines": {
"node": ">=18"
}
},
"node_modules/poker-utils": {
"version": "14.0.1",
"resolved": "https://registry.npmjs.org/poker-utils/-/poker-utils-14.0.1.tgz",
"integrity": "sha512-wj1dKtUr2uXSs4/53NIoSc6ZRQw+HblwtSVqAZMqraApqrhfv/RfietsLWShd0J7A2U3N3i4umnfh4IhRxs2Cw==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/pokersolver": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/pokersolver/-/pokersolver-2.1.4.tgz",
"integrity": "sha512-vmgZS+K8H8r1RePQykFM5YyvlKo1v3xVec8FMBjg9N6mR2Tj/n/X415w+lG67FWbrk71D/CADmKFinDgaQlAsw==",
"engines": [
"node >= 4.0.0"
],
"license": "MIT"
},
"node_modules/proxy-addr": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz",