How NashForge Won Four Seasons in a Row
NashForge has won the last four Chipzen seasons, and no other bot has won two. Its builder, Dheirav, on the solver that beat his learned methods, the four stages every version passes before it plays, and the two times his own measurements fooled him.
NashForge has won the last four Chipzen seasons: 6, 7, 8 and 9. No other bot has won two. By its builder's count, the version that plays is only a couple of months old.

The builder is Dheirav, a final-year computer science and engineering student in India. NashForge is a solo project and a hobby. He gives it one to two hours a day, and in a season week the clock matters as much as the hours, because the fixtures land late at night for him. The bot is a solver with a C++ core, its strategy computed before it sits down, and it has competed nowhere but Chipzen.
Dheirav was kind enough to answer some of our questions and share what he has learned while working on his bot: how he measures a change, and what a version has to pass before it plays.
From evolutionary search to a solver
NashForge did not start as a poker bot, or as a solver. It started with YouTube. "It started after I watched Sebastian Lague and Code Bullet on YouTube, who train bots with evolutionary learning and similar methods, and I liked the evolutionary approach in particular, so that is where I started." Before poker there was a chess engine in C++ and a bot for the board game Brass: Birmingham. Both are on his GitHub.
The first poker version, in January, was an evolutionary search on a rules engine he wrote himself. Reinforcement learning followed. Then the project sat until the summer. "I came back to the project in July or August, and that is when it turned into what it is now. The first step was an audit in August."
The audit is where the story gets good. He noticed that an untrained network, one with random weights, was beating his test opponents by a wide margin. "That impossible number led me to the cause: the scoring function was crediting the wrong player, and the deck was dealing the same two hands over and over. Everything measured with it was invalid." He withdrew the early results and started again.
The second trap was quieter. He had been reading learning curves from short runs of a few thousand hands. "At that size the error is far larger than the effect, so an apparent improvement was noise, and the real effect only appeared in a much longer test. Since then I do not read a curve without checking how many hands are behind it."
With the measuring fixed, he built a solver in mid-August and put all three methods on the same engine. "The solver won by a wide margin, while the two learned methods stayed well behind it however much training they got." The heavy parts moved into C++, and in September it came to Chipzen.
The stack, for those who want it: Python 3.12 for most of it, a C++ core for the solver built with CMake and nanobind, numpy and numba for the numerical work, PyTorch for the reinforcement learning comparison, pygame for a small viewer where a person can play the bot, and pytest, with close to nine hundred tests.
The four stages before a rated match
Since September, the work has mostly been measuring changes one at a time rather than building new things. A new version does not go straight into a rated match. It goes through four stages, and each is there to catch a different kind of mistake:
- Making sure the training itself is sound, before I trust anything it produces.
- Playing it against my other versions, to see that it holds up.
- Running it over hands I have already played, to see what it would have changed.
- A small run of real matches, to check that it behaves properly in the real arena.
The last stage is not a verdict. "A small run cannot prove a version is stronger, so I read it as a check that nothing is broken and not as a result." The rule that holds it together: "Nothing changes on match day. Whatever plays in a fixture was chosen and tested beforehand."
He compares it to how a serious poker player prepares. "They do not try a new idea in a big game. They work it out away from the table, look back at old hands to see what it would have changed, try it at small stakes first, and treat one short winning or losing session as mostly luck and not as proof. And just as a good player sticks to the plan on the night and does not rewrite it mid-session, I keep the bot on the plan it was tested on."
The field and the arena
I asked what he makes of the other bots. "Some bots call almost everything and only bet with a strong hand, which makes them predictable in a way that rewards patience. Some are aggressive and put in a lot of raises, which makes every pot larger and every decision harder. Others fold a great deal and give up pots without a fight." The ones that interest him most are the ones that change mid-season, "because a measurement of them from last week can stop being true, so anything built on old data has to be checked again."
On the arena itself, the thing he values is that it is the same for everyone. "Every fixture has a published start time, every rated match has a replay, and the clock and the API are the same for everyone, so the competition is about the bots." The public record of hands is what made much of his testing possible. His one wish is for more room for builders to compare notes on how they build and test.
Six-max tempts him, but not yet. He wants the heads-up bot finished first, because "I would not trust a strong six-player bot built on a heads-up bot I had not finished measuring."
A bot called Nashforgebeater
There is now a bot on the platform called Nashforgebeater. I asked him whether he sees a challenger taking the title. He loved the question.
"Think about what that means: people are building bots specifically to beat me. You do not train against a bot nobody cares about, so I take it as the best compliment this project could get. And I love the challenge. So to every challenger out there, whether you are called Nashforgebeater or anything else: bring it on. Study the replays, build your counter, and come and take the title. I will not make it easy, but I will respect whoever manages it. May the best bot win."
Nashforgebeater is in the Season 10 field.
Seven rules for a first bot
His advice for someone building a first bot, in his words:
- Check your solver on a tiny game with a known answer, like Kuhn poker, before you trust it on a big one. A solver that has converged to the wrong thing looks exactly like one that has converged to the right thing.
- Measure with enough hands. A result from a few thousand hands is mostly noise, and I have been fooled by it more than once.
- Test with the same cards on both sides, so that luck cancels out, and make sure your test reads zero when a bot plays itself. If it does not, the test is broken and not the bot.
- Keep every change small and switchable, and change one thing at a time, so you can tell which change helped.
- Write down what you tried, including what failed and what you withdrew. A short, honest handover note saves you from repeating the same mistake a month later.
- Test the boring parts, like connecting, timing and recovering from a crash, as hard as the strategy. A bot that does not turn up cannot win.
- Never change what plays on match day. Pick it, test it and freeze it beforehand.
The last thing he said is the one he wants readers to take away. "Most of the real progress came from finding out where my own measurements were wrong, and not from a clever new idea. I would like readers to take that away, because it applies to any bot, whatever it plays."
NashForge is built by Dheirav. He is on LinkedIn and GitHub, and the public core of NashForge is at github.com/Dheirav/NashForge-core. The matches he talks about are on the season pages, replays included. Entering a bot is free.