ericgjackson / slumbot2019 Goto Github PK
View Code? Open in Web Editor NEWImplementations of CFR for solving a variety of Holdem-like poker games
License: MIT License
Implementations of CFR for solving a variety of Holdem-like poker games
License: MIT License
At the end of a hand, in addition of baseline_winnings
, I would like to compare my line to the baseline further. This would include:
{"action":"b250b750f","client_pos":1,"hole_cards":["Ts","7d"],"board":[],"bot_hole_cards":["4d","4c"],"winnings":-250,"won_pot":-1000,"session_num_hands":18,"baseline_winnings":-650,"session_total":9050,"session_baseline_total":4450}
)Hello.
I have been trying to use the code for minimizing regret and solving Texas Holdem (holdem_params).
The thing is that solve_all_subgames seems to run forever while it creates huge files with parameters I have been giving. I have to say that I'm not sure if parameters I have been giving are correct or if my buckets that I have been using are correct. I have tried to read source code to figure out the exact meaning of each parameter, but can't figure it out.
here is one of the input I have been trying:
../bin/solve_all_subgames holdem_params nhs2_params none_params mb1b1_params mb1b1_params tcfr_params cfrps_params 3 0 200 unsafe cbrs card zerosum avg none disk 1 10
The input I used for building "hs" buckets is in README.md.
Also in the holdem_results file, configuration for buckets is "nnwml1wml1". I have been trying to replicate those buckets, but I have no idea what parameters are being given to build_rollout_features to create "wml1" buckets. Any tips?
Anyway many thanks for publicizing this project. It's really interesting.
hi @ericgjackson
I want to know the relationship between "the number of the boards" and "the number of the buckets". I know there are 169 buckets on the pre-flop,1755 buckets on the flop after removing isomorphisms. But the number of the boards makes me confused .
look forward to your reply :)
st 0:1 boards 169 buckets
st 1 : 1755 boards 1286792 buckets
st 2 : 63193 boards 1927 buckets
st 3: 2554656 boards 1950 buckets
{'old_action': 'b200b1103c/b940c/b778b6957', 'action': 'b200b1103c/b940c/b778b6957b13136b17957', 'client_pos': 0, 'hole_cards': ['Ah', 'Qc'], 'board': ['Qh', 'Jd', '6s', 'Ks']}
Action: b200b1103c/b940c/b778b6957b13136b17957
Client hole cards: ['Ah', 'Qc']
Board: ['Qh', 'Jd', '6s', 'Ks']
Error parsing action b200b1103c/b940c/b778b6957b13136b17957: Bet too small
b13136 is my action which is legal(minraise), b17957 is slumbot's action, same as Allin, however api judge its bet size error
Hi Eric,
I am trying to compile your code but get stuck when compiling vcfr_state.cpp:
gcc -std=c++17 -Wall -O3 -march=native -ffast-math -flto -c -o obj/vcfr_state.o src/vcfr_state.cpp
src/vcfr_state.cpp:27:22: error: no matching constructor for initialization of
'shared_ptr<int []>'
shared_ptr<int []> street_buckets(new int[num]);
Is there a simple way to fix this?
Thanks!
$ make bin/head_to_head
gcc -std=c++17 -Wall -O3 -march=native -ffast-math -flto -c -o obj/head_to_head.o src/head_to_head.cpp
src/head_to_head.cpp: In member function ‘void Player::Nonterminal(Node*, Node*, const string&, const ReachProbs&)’:
src/head_to_head.cpp:456:38: error: cannot convert ‘std::shared_ptr<CFRValues>’ to ‘const CFRValues*’ in assignment
sumprobs = b_eg_cfr_->Sumprobs();
^
src/head_to_head.cpp:468:38: error: cannot convert ‘std::shared_ptr<CFRValues>’ to ‘const CFRValues*’ in assignment
sumprobs = a_eg_cfr_->Sumprobs();
^
make: *** [obj/head_to_head.o] Error 1
make bin/play
gcc -std=c++17 -Wall -O3 -march=native -ffast-math -flto -c -o obj/play.o src/play.cpp
src/play.cpp: In constructor ‘Player::Player(const BettingAbstraction&, const BettingAbstraction&, const CardAbstraction&, const CardAbstraction&, const CFRConfig&, const CFRConfig&, int, int)’:
src/play.cpp:503:78: error: no matching function for call to ‘CFRValues::Read(char [500], int&, const BettingTree*, const char [2], int, bool)’
a_probs_->Read(dir, a_it, a_betting_trees_->GetBettingTree(), "x", -1, true);
^
In file included from src/play.cpp:41:0:
src/cfr_values.h:30:8: note: candidate: void CFRValues::Read(const char*, int, const BettingTree*, const string&, int, bool, bool)
void Read(const char *dir, int it, const BettingTree *betting_tree,
^~~~
src/cfr_values.h:30:8: note: candidate expects 7 arguments, 6 provided
src/cfr_values.h:67:8: note: candidate: void CFRValues::Read(Node*, Reader***, void***, int)
void Read(Node *node, Reader ***readers, void ***decompressors, int p);
^~~~
src/cfr_values.h:67:8: note: candidate expects 4 arguments, 6 provided
src/play.cpp:510:78: error: no matching function for call to ‘CFRValues::Read(char [500], int&, const BettingTree*, const char [2], int, bool)’
b_probs_->Read(dir, b_it, b_betting_trees_->GetBettingTree(), "x", -1, true);
^
In file included from src/play.cpp:41:0:
src/cfr_values.h:30:8: note: candidate: void CFRValues::Read(const char*, int, const BettingTree*, const string&, int, bool, bool)
void Read(const char *dir, int it, const BettingTree *betting_tree,
^~~~
src/cfr_values.h:30:8: note: candidate expects 7 arguments, 6 provided
src/cfr_values.h:67:8: note: candidate: void CFRValues::Read(Node*, Reader***, void***, int)
void Read(Node *node, Reader ***readers, void ***decompressors, int p);
^~~~
src/cfr_values.h:67:8: note: candidate expects 4 arguments, 6 provided
make: *** [obj/play.o] Error 1
hi Eric. I have run the code with
../bin/solve_all_subgames GameParams/ms1f3_params CardAbstraction/NLFH_params CardAbstraction/NLFH_params \
BettingAbstraction/mb1b2_params BettingAbstraction/mb1b2_params CFR/cfrps_params CFR/cfrps_params \
1 10000 10000 unsafe cfrs bucket raw avg none mem 1 8
I also ran the code with the config before this. but it always encounter segmentfault when running code to solve the subgame.
I've read the code for a long time, but I'm still confused. could u plz give some tips for this ? thks a lot.
Hi,ericgjackson,
I want to connet with acpc server ,but there is an error when I start the client by running /code2/slumbot2019-master/runs$ ../bin/run_bot holdem_params nhs2_params mb4b3_params tcfr_params 0 2 "this is my hostname" 10000:
Constructed agent
Calling MainLoop
Fri Nov 6 02:46:00 2020: WARNING: ReadHTTPLine: failed with partial line "0000000004null"; fd 11
Exited MainLoop
I just get the hostname by hostname command in linux.
and the acpc server is running with printed information:
Fri Nov 6 02:38:01 2020: Listening for connection on port 10000
Hello,
Is it a bug in mp_betting_tree.cpp line 429
i check when calling CreateMPStreet, street will add 1 outside, so is it unnessasary to add 1 again?
i think the right code is below
int next_player_to_act = NextPlayerToAct(Game::FirstToAct(street), folded)
while old code is
int next_player_to_act =NextPlayerToAct(Game::FirstToAct(street + 1), folded);
I was just exploring the sample_api.py script, but i am unable to make any request.
I get a exception as "Connection aborted.', ConnectionResetError(54, 'Connection reset by peer')"
Hi, @ericgjackson Thanks for your open source, you are doing an amazing job!
In slumbot2019/src/#solve_one_subgame_unsafe.cpp# line 478-481 I notice you have already implemented the unsafe, CFR-D, MaxMargin subgame solving, what is the combined means? I have noticed it is not Noam reach subgame solving, do you have the plan to implement it?
Hi Eric - what is the best way to contact you to discuss a coding project?
So I just recently played againts slumbot and I want to ask if I encountered bug or Im just confused.
State I encountered was following b200b2179b4200
So me being BB, slumbot SB
SB - 50 and BB 100
SB is first to act. So slumbot raises to 200 which make sense, so he is adding 150 to pot.
Then Im raising by 2079, since Im 100 as BB in pot commited already final bet is 2179.
But then slumbut adding to po 4000. I added 2079 (previous bet), and by standart poker rules, opponent must raise at least double of previous bet which would tell me min raise here is 4158 (+ 200 of first raise slumbot made) = 4358?
Do I miss something?
I ran the following code with Deno, with Node, and in the browser console:
fetch("https://slumbot.com/api/new_hand", {
method: "POST",
headers: { "content-type": "application/json" },
body: "{}",
}).then(console.log);
Each time, I got a 400 response. I tried with other endpoints too, including with a token I got from a call in another program - cURL, Python, and Go worked fine.
Is the code wrong, is there something that Javascript's fetch
doesn't implement, or something else?
Thanks for making this project available.
Following the instructions after running CFR+ on the simple game we can calculate exploitability and have the regrets in the /data directory. Is there a way to display the information sets in a human readable format?
Hey, as it seems I cant enter the website nor get any response from the API currently
I ran the MCCFR example and now want to inspect the strategy.
Preflop works like a charm:
../bin/show_preflop_strategy holdem_params nhs2_params mb1b1_params tcfr_params 0 cum
I do get the same result using this:
../bin/show_probs_at_node holdem_params nhs2_params mb1b1_params tcfr_params 0 cum ""
This gives the strategy for second player after first player limps:
../bin/show_probs_at_node holdem_params nhs2_params mb1b1_params tcfr_params 0 cum c
This however returns a segmentation fault(I am not out of memory):
../bin/show_probs_at_node holdem_params nhs2_params mb1b1_params tcfr_params 0 cum cc
How can I see the flop strategy? How do I encode the board cards in the betting sequence?
Thanks for any hints.
Hi Eric,
I'm testing my bot against Slumbot using the API script, and getting errors like:
Error parsing action b200b1250c/kb750b18650b18750: Bet too small
{'old_action': 'b200b1250c/', 'action': 'b200b1250c/kb750', 'client_pos': 0, 'hole_cards': ['Ad', 'Jc'], 'board': ['8h', '4d', '2s']}
Action: b200b1250c/kb750
Client hole cards: ['Ad', 'Jc']
Board: ['8h', '4d', '2s']
Sending incremental action: b18650
-----------------
{'old_action': 'b200b1250c/kb750', 'action': 'b200b1250c/kb750b18650b18750', 'client_pos': 0, 'hole_cards': ['Ad', 'Jc'], 'board': ['8h', '4d', '2s']}
Action: b200b1250c/kb750b18650b18750
Client hole cards: ['Ad', 'Jc']
Board: ['8h', '4d', '2s']
So in this case, my bot made a bet of 18650, and slumbot responded with a bet size of 18750, which should be illegal. It seems to be happening with bet sizes near the all-in amount. I'm probably misunderstanding something here, but just wanted to double check.
Also, is there documentation of the action string format? Does client_pos = 0
mean that my bot is the dealer?
Thanks!
cool open source for the popular slumbot.
does mccfr can converge faster than cfr+ in your implementation. any acceleration technique for the implementation of mccfr.
In my experiment, i find mccfr is much slower than cfr+. If we want to achieve a low-exploitability strategy, why we need to run mccfr when solving the subgame of hunl?
I used the command ../bin/show_probs_at_node ms1f3_params none_params mb1b1_params cfrps_params 500 cum c. This gave me a segmentation fault. I'm not sure what's causing this as it appears others do not run into this issue. I'm using WSL and Ubuntu to run the terminal so maybe that's the problem? Can anyone clarify what is the problem here?
Hey,
My team and I are working on a poker project and are looking to hire experienced CFR and C++ developers.
Is this something you would be interested in? We will happily pay a premium to your regular going rate. You can contact me via email - [email protected]
Best,
TJW89
Hi, @ericgjackson I am wondering what’s the purpose of build_betting_tree?
Can you give an Intuitive example of the betting tree?
i.e., after executing ../bin/build_betting_tree ms1f3_params mb1b1_params
What has been saved on the disk?
Thanks
Doesn't work out for me.
#ifdef __CYGWIN__
works.
Hi, i tested my bot against your API on slumbot.com and found this strange hand in my records.
My Hand: 8H high straight flush loosing against an AK with (no Joke) 3H 4H 5H 6H 7H board . Here are my records
{
"_id": {
"$oid": "6663331f4a6fab7a117f02b0"
},
"name": "D",
"date": {
"$date": "2024-06-07T16:19:43.358Z"
},
"bb": 100,
"sb": 50,
"pot": 40000,
"streets": 0,
"showDown": true,
"players": [
{
"_user": {
"$oid": "6658806b4ff4dcb254aa5eec"
},
"name": "SlumBot",
"money": 20000,
"pocket": [
"AD",
"KC"
],
"winning": 20000
},
{
"_user": {
"$oid": "657ad579ebf85d7bd01395ad"
},
"name": "trainer",
"money": 20000,
"pocket": [
"8H",
"8D"
],
"winning": 0
}
],
"actions": [
"p0r150",
"p1r700",
"p0r2200",
"p1r8800",
"p0r17600",
"p1c"
],
"actionString": "b200b800b2400b9600b20000c///",
"board": [
"3H",
"4H",
"5H",
"6H",
"7H"
],
"__v": 0
}
When running ../bin/build_unique_buckets holdem_params 3 hs hs from the tutorial section of the readme for MCCFR, I get the following error: terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted
ecfr.h
Dear @ericgjackson
I developed a poker agent and try to evaluate it on slumbot.com. However I found something wrong on the website, showing that "no response from server on slumbot.com". Could you help solve this problem? Thanks!
Dear @ericgjackson
I developed a poker agent recently and want to compare it with slumbot which is the only public agent on the Internet. Unfortunately, the website crashed this morning and the error message is "Server error: couldn't save session". Could you help maintain the website "www.slumbot.com"?
Thank you very much! O(∩_∩)O
Dear @ericgjackson
I am wondering how to use your code to train a bot to play heads-up no-limit Texas Holdem (like this one www.slumbot.com)
There are lot of code in this repo, I want to have an intuitive understanding of the project by training a heads-up no-limit Texas Holdem bot step by step.
Thank you very much! O(∩_∩)O
It appears the entire server is down since at least yesterday.
Hi Eric,
Thanks for making this available.
This GetNewBetTos function call is used in building the multiplayer betting tree, but its implementation assumes 2 players only when calculating the pot (and later on, the pot fractions)
Is this a bug or am I missing something ?
Hi, The leaderboard is empty, Any idea why and when will it be recovered?
Hi, @ericgjackson
I want to learn the CFR algorithm with your wonderful code
But when I run
make bin/build_hand_value_tree
The following error occurs
src/vcfr_state.cpp: In function ‘std::shared_ptr<double []> AllocateOppProbs()’:
src/vcfr_state.cpp:38:46: error: no match for ‘operator[]’ (operand types are ‘std::shared_ptr<double []>’ and ‘int’)
for (int i = 0; i < num_enc; ++i) opp_probs[i] = 1.0;
^
src/vcfr_state.cpp: In constructor ‘VCFRState::VCFRState(int, const HandTree*)’:
src/vcfr_state.cpp:55:94: error: cannot convert ‘double (*)[]’ to ‘double*’ for argument ‘3’ to ‘void CommonBetResponseCalcs(int, const CanonicalCards*, double*, double*, double*)’
CommonBetResponseCalcs(0, hands, opp_probs_.get(), &sum_opp_probs_, total_card_probs_.get());
^
src/vcfr_state.cpp: In member function ‘int* VCFRState::StreetBuckets(int) const’:
src/vcfr_state.cpp:103:39: error: invalid use of array with unspecified bounds
return street_buckets_.get() + st * max_num_hole_card_pairs;
^
src/vcfr_state.cpp:103:39: error: cannot convert ‘int (*)[]’ to ‘int*’ in return
In file included from /usr/include/c++/5/bits/shared_ptr.h:52:0,
from /usr/include/c++/5/memory:82,
from src/vcfr_state.cpp:11:
/usr/include/c++/5/bits/shared_ptr_base.h: In instantiation of ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*) [with _Tp1 = int; _Tp = int []; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’:
/usr/include/c++/5/bits/shared_ptr.h:117:32: required from ‘std::shared_ptr<_Tp>::shared_ptr(_Tp1*) [with _Tp1 = int; _Tp = int []]’
src/vcfr_state.cpp:27:49: required from here
/usr/include/c++/5/bits/shared_ptr_base.h:882:39: error: cannot convert ‘int*’ to ‘int (*)[]’ in initialization
: _M_ptr(__p), _M_refcount(__p)
^
/usr/include/c++/5/bits/shared_ptr_base.h: In instantiation of ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*) [with _Tp1 = double; _Tp = double []; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’:
/usr/include/c++/5/bits/shared_ptr.h:117:32: required from ‘std::shared_ptr<_Tp>::shared_ptr(_Tp1*) [with _Tp1 = double; _Tp = double []]’
src/vcfr_state.cpp:37:54: required from here
/usr/include/c++/5/bits/shared_ptr_base.h:882:39: error: cannot convert ‘double*’ to ‘double (*)[]’ in initialization
Makefile:29: recipe for target 'obj/vcfr_state.o' failed
make: *** [obj/vcfr_state.o] Error 1
NB: this is a custom UI I developed. You can find the source code here: https://github.com/JbCourtois/SlumbotUI
In the "/api/act" entpoint, my agent can input actions like "b400b19999b20000f" and take control of Slumbot betting.
My bot Hackbot exploits this flaw, feel free to remove it from the leaderboard.
When I follow the instructions in the readme for the MCCFR example I get an error when running the last command:
../bin/run_tcfr holdem_params nhs2_params mb1b1_params ecfr_params 8 1 2 100000000 1 -> "Unknown algorithm: ecfr
"
Looking at run_tcfr.cpp this looks like the intended response and run_tcfr is not supposed to be run with ecfr_params? When I change it to: ../bin/run_tcfr holdem_params nhs2_params mb1b1_params tcfr_params 8 1 2 100000000 1
I get the error message saying that /data/cfr//holdem.2.nhs2.13.4.3.mb1b1.tcfr/regrets.x.0.0.0.0.p0.i can not be opened(directory does not exists indeed). All the preparing commands went through without any error. The CFR+ example got me an appropriate directory. What am I missing?
Thanks for any help.
Hi @ericgjackson,
I been studying a bit a slumbot, and I think I found a bug.
in README.md
../bin/build_hand_value_tree holdem_params
../bin/build_betting_tree holdem_params mb1b1_params
when building betting tree Im getting illegal access, coming from:
void BettingTreeBuilder::Write(Node *node,
vector<vector<int>> *num_nonterminals,
Writer *writer) {
.....
if (nt_first_seen) {
id = (*num_nonterminals)[pa][st]++;
node->SetNonterminalID(id);
}
the variable of player acting, pa
goes out of range of num_nonterminals.
Switching from:
root_ = CreateMPTree(target_player_, &terminal_id);
to:
root_ = CreateNoLimitTree1(target_player_, &terminal_id);
seems to fix the issue.
On separate note, could you tell us what parameters has been used for training slumbot online version?
Im trying to replicate that work, to have local benchmark for deep learning research Im doing.
Im interested about betting/card abstraction, what amount of iterations?
Thank you very much.
I want to to compile an instance to call from a bash script, instead of making a network call to the website's API. Is this possible? I've tried the examples in the readme and felt out a few other configurations, but I couldn't figure out how to send input and so on.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.