TexasHoldemSolverJava: an open source CFR solver for hold'em and short deck
A Java implemented Texas holdem and short deck Solver
At a glance
- What is it?
- TexasHoldemSolverJava is a Java implementation of a Texas Hold'em and short deck solver with a graph style interface and a Python calling layer, focused on post-flop situations. The project states plainly that it still works but is no longer maintained, and points at a C++ rewrite as the version to use.
- Who is it for?
- TexasHoldemSolverJava suits a researcher or advanced player who wants to read the algorithm behind a commercial solver's output, or who needs CFR solve results for a post-flop spot without a licence, and the Python calling layer makes it easy to drive from an existing analysis pipeline.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A solver that shows its working, aimed at post-flop spots
TexasHoldemSolverJava is described as an open sourced, efficient Texas Hold'em and short deck solver, with a Java implementation that has a pio-solver-like interface and supports cross-language calls, by default through Python and the command line.
The positioning against commercial tools is stated in the documentation with unusual candour. It focuses on solving post-flop situations, its results are aligned with piosolver, and on turn and river its speed is even faster than piosolver, while on the flop it is slower. The features list repeats the speed claim with the turn struck out and the river left standing.
So the tool occupies a specific slot: post-flop analysis, comparable output to the reference commercial solver, fully open source and free, with a simple interface.
The stated users are high-level Texas Hold'em players and scholars in the field of incomplete information games. That second group is the more interesting one for an engineering audience, because the repository is a readable Java implementation of a real algorithm rather than a wrapped binary.
The alternative framing is worth keeping in mind. A commercial solver is a black box you query. This one exposes the game tree, the rule configuration and the range syntax, so you can read how the tree is built and how the algorithm is parameterised. That is what makes it useful to a scholar and less useful to a player who just wants answers, since a commercial tool gives those faster and with more polish.
Solving means building a game tree from a rule configuration
The mechanism is a counterfactual regret minimisation solver driven by an explicitly constructed game tree, and the construction step is where most of the configuration work happens.
First, general rules are loaded from a YAML file describing what actions are legal in each situation, for example that you can check or raise after a check, and that you can raise, call or fold after a raise.
# Load some general rules of texas holdem. e.g. you can check/raise after a check, you can raise/call/fold after a raise.
with open('resources/yamls/general_rule.yaml') as fhdl:
conf = yaml.load(fhdl)
# Use RulesBuilder to convert these rules to game tree.
rule = RulesBuilder(
conf,
current_commit = [2,2], # current bets of both players(p0 and p1)
current_round = 3, # current round of the game, 1 for preflop, 2 for flop,3 for turn,4 for river
raise_limit = 3, # the limit of numbers of raises
check_limit = 2, # how many times you can check, in 2-player texas holdem, it's 2
small_blind = 0.5, # amount of small blind (SB)
big_blind = 1, # amount of big blind (BB)
stack = 10, # the amount of chips for both sides. If two player have different chip amount, fill in the smaller number here. For example player1 have $100 chip and player2 have $150, fill in 100 here.
bet_sizes = ["0.5_pot","1_pot","2_pot","all-in"], # bet sizes and raise sizes considered in the game tree,can be number e.g. 1,1.5 or in the proportion of the pot e.g. "0.5_pot","1_pot"
)Several of those parameters deserve attention. current_round uses 1 for preflop, 2 for flop, 3 for turn and 4 for river. raise_limit and check_limit bound the tree, and the comment on check_limit notes it is 2 in two player hold'em. The stack parameter is documented with the detail that when the two players have different amounts you fill in the smaller number.
The bet_sizes list accepts either absolute numbers or pot proportions written as strings such as "0.5_pot", "1_pot" and "2_pot", plus all-in. This is the knob that determines how large the tree gets, and therefore how long the solve takes and how precise the result is.
The tree is then built and written to disk, and loaded back into the solver.
gameTree = PartGameTreeBuilder(rule)
# save the game tree to disk
gameTree.gen_km_json("./.tree.km",limit=np.inf,ret_json=True)ps_holdem.build_game_tree("./.tree.km")The split into build, serialise and load is a real design decision. Persisting the tree means you can reuse an expensive tree across many solves with different ranges, which is the normal workflow when studying a spot.
Ranges are written as weighted hand combinations
The solving call takes two ranges, the public board, and the algorithm parameters.
result = ps_holdem.train(
"AA:0.5,KK:0.9,QQ:0.8,97,96,87,86,76", # player1's range, seperate by ','; you can write range in two ways: (1) "KK:0.5" stands for player have K-pair weighted 0.5 (2) "KK" stands for player have a K-pair weighted 1
"AA:0.8,KK:0.2,QQ:0.3,86,76:0.9", # player2's range
"Kd,Jd,Td,7s", # the revealed public cards. In turn there are four.
50, # the iterations for cfr algorithm
10, # the gap to print exploitability
False, # whether to print debug info
True, # whether to use parallel technology
"output_strategy.json", # for to write output strategy. When set to None the strategy json will be returned in result of this method.
"log.txt", # log file
"discounted_cfr", # the solver algorithm ,support "cfr" vanilla cfr algorithm, "cfr_plus" faster cfr+ algorithm,"discounted_cfr" discounted cfr ++ al
)The range syntax is compact and worth parsing carefully. Hand combinations are separated by commas, and each can carry a weight after a colon, so AA:0.5 means a player holding an AA pair with weight 0.5, while a bare KK means the same thing with weight 1.
The board is given as concrete cards, and the comment notes there are four on the turn.
The numeric parameters are the ones to understand. The first is the number of iterations for the CFR algorithm, which is the main dial between solve time and result quality. The second is the gap to print exploitability, which is how often the solver reports how far the strategy is from the theoretical optimum. Then a debug flag, a parallel flag, the output strategy file name, and the log file.
The last argument selects the algorithm, and the comment names three: cfr for vanilla CFR, cfr_plus for the faster CFR+ variant, and discounted_cfr for discounted CFR++.
For a tool aimed at scholars, that algorithm choice is the interesting one. Vanilla CFR is the baseline, CFR+ adds regret truncation to converge faster, and discounted CFR++ is what the modern solvers use. Being able to switch between them on the same tree makes it a reasonable teaching and research instrument.
Java underneath, Python on top, and the JPype bridge between them
The calling model is unusual and worth being explicit about, because it explains the dependency list.
The solver itself is a Java program, RiverSolver.jar, but the documentation says that although written in Java, TexasHoldemSolverJava is by default called through Python. The Python side starts the JVM in-process and loads the solver class through JPype.
from jpype import *
import yaml
import numpy as np
import sys
sys.path.append("resources")
from python.TreeBuilder import *startJVM(getDefaultJVMPath(), "-ea", "-Djava.class.path=%s" % "./RiverSolver.jar")
PokerSolver = JClass('icybee.solver.runtime.PokerSolver')The class is then constructed with the hand comparison dictionary and its parameters.
ps_holdem = PokerSolver("Dic5Compairer",
"./resources/compairer/card5_dic_sorted.txt", # Load hand compair dictionary file. Holdem and shortdeck use different dictionary file
2598961, # valid line of dictionary file
['A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3'], # figure of cards
['h', 's', 'd', 'c'] # pattern of cards
)The dictionary file is the precomputed hand ranking table, and the comment notes that hold'em and short deck use different dictionary files. That is a meaningful implementation detail: the solver ranks hands from a precomputed table rather than evaluating every combination at runtime, and short deck needs its own table because the rankings differ.
The Python side therefore needs a few extra packages on top of a JVM.
pip3 install jpype
pip3 install numpy
pip3 install yaml
pip3 install networkx
pip3 install matplotlibjpype is the bridge, numpy is used for the tree limit, pyyaml parses the rule file, and networkx and matplotlib are there for graph and plotting work.
This architecture has an obvious consequence. You need a working JVM and a working Python in the same process, and the two runtimes must agree on paths, since the code appends the resources directory to the path and passes a relative classpath. When it works, the payoff is that a Python analysis script can call a real CFR solver as a library.
Installing from a release package, and the Java version confusion
Installation is a download and an unzip, with no build step for the user.
--- Solver
|- resources
|- java_interface.py
|- RiverSolver.jar
|- riversolver.shRiverSolver.jar is the solver program file, java_interface.py is the sample code for calling the solver through Python, and riversolver.sh contains sample code for command line calls. The documentation says install is done, and it is that simple.
The Python sample includes test cases for a short flop situation, a short turn situation, a short river situation, a hold'em turn situation and a hold'em river situation, and you run them with python3 java_interface.py after downloading the release package.
For the interface itself, the documentation says to double click the jar to open the GUI, after making sure the right version of Java is installed.
The Java requirements are where the documentation contradicts itself, and you need to sort this out before you start. One line says to install a 64bit Java Runtime Environment first, with a link to the Java 8 JRE downloads. A later line says the solver also relies on JRE 11.0.2 as its runtime and to install Java JRE 11.0.2 in advance. The GUI section says to make sure the right version of Java is installed, 64bit, java 10.x or java 11.x.
Four different version statements on one page. The likely reading is that the 64bit JRE 8 download link is outdated and the actual runtime requirement is Java 11, but the documentation does not settle it. Anyone installing this should determine the required version empirically rather than trusting the download link, and the repository also contains a pom.xml and a src/ directory, so the source is there if you would rather build it than use the release package.
The project asks you to use the C++ version instead
The most important line in the repository is the warning at the top. The project still works but it is no longer maintained, and the reader is asked to check the latest C++ version, TexasSolver, hosted in the same organisation's GitHub.
That single line changes how you should read everything else. The releases confirm it: 0.1.0 on 2021-02-16 and 0.2.0 on 2021-03-14, both more than five years ago, with no tagged release since. The last push was on 2026-10-06, so there is still activity on the tree, but the published versions have not moved since March 2021.
For an evaluator, the reasonable conclusion is that this repository is best treated as a reference implementation rather than a dependency. Its value is that you can read a complete Java CFR solver, with the game tree construction, the hand comparer, the rule builder and the algorithm selection all visible in one place, and that it is MIT licensed so the code can be studied and reused under those terms. This is not legal advice, but the terms are conventional.
The repository layout supports that reading. There is a benchmarks/ directory, which suggests the authors were measuring solver performance, an img/ directory with the interface screenshots, a pom.xml for the Maven build, and a src/ directory. The README is also available in Chinese as README.zh-CN.md.
If your goal is to produce accurate post-flop analyses rather than to study the algorithm, the successor project is the one to evaluate, because it inherits the same idea of an open solver without the five year old Java dependency and the inconsistent version instructions.
Editorial conclusion
TexasHoldemSolverJava suits a researcher or advanced player who wants to read the algorithm behind a commercial solver's output, or who needs CFR solve results for a post-flop spot without a licence, and the Python calling layer makes it easy to drive from an existing analysis pipeline. It does not suit a developer starting a new tool, because the project itself says it is no longer maintained and recommends the C++ TexasSolver instead, and the Java runtime requirements are contradictory in the documentation. Before building on it, read the deprecation line at the top of the repository, decide whether the C++ successor gives you the same interface, and confirm which Java version your machine actually has, since the install notes mention Java 8, Java 10.x, Java 11.x and JRE 11.0.2 in the same page.
Frequently asked questions
Is TexasHoldemSolverJava still maintained?
No. The repository states in a warning at the top that the project still works but is no longer maintained, and asks readers to check the latest C++ version, TexasSolver. The tagged releases are 0.1.0 from 2021-02-16 and 0.2.0 from 2021-03-14.
How do I install TexasHoldemSolverJava?
Download the release package from the GitHub releases page and unzip it, which gives a folder with resources, java_interface.py, RiverSolver.jar and riversolver.sh. The documentation also says to install a 64bit Java Runtime Environment first, though the page names several different Java versions.
How is TexasHoldemSolverJava called from Python?
Python starts the JVM in-process with JPype and loads the solver class, then constructs PokerSolver with a hand comparison dictionary and card notation. The Python dependencies listed are jpype, numpy, yaml, networkx and matplotlib.
Which CFR algorithms does TexasHoldemSolverJava support?
The solver algorithm argument accepts cfr for the vanilla algorithm, cfr_plus for the faster CFR+ variant, and discounted_cfr for discounted CFR++.
What does TexasHoldemSolverJava focus on compared to piosolver?
It focuses on solving post-flop situations, and the documentation states the results are almost the same as piosolver. On turn and river its calculation speed is said to exceed piosolver, while on the flop it is slower.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bupticybee-texasholdemsolverjava)Was this useful?