-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathreadme.txt
1006 lines (694 loc) · 43.8 KB
/
readme.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
OOPoker
-------
.------..------..------..------..------..------..------.
|O.--. ||O.--. ||P.--. ||O.--. ||K.--. ||E.--. ||R.--. |
| :/\: || :/\: || :/\: || :/\: || :/\: || (\/) || :(): |
| :\/: || :\/: || (__) || :\/: || :\/: || :\/: || ()() |
| '--'O|| '--'O|| '--'P|| '--'O|| '--'K|| '--'E|| '--'R|
`------'`------'`------'`------'`------'`------'`------'
Table of Contents:
0 Introduction
1 Terminology
2 Using the program
2.1 System Requirements
2.2 Gameplay
2.3 Battling AIs
2.4 Player Statistics
3 Programming AIs
3.1 Really Quickly Getting Started
3.2 C++, Compiler and IDE.
3.2.1 C++
3.2.2 Compiler
3.2.3 Language
3.3 Implementing the AI
3.4 Putting your AI in the game
3.5 Utility Functions
3.6 Fast Evaluation (For Win Equity)
3.7 OOPoker Code Overview
3.8 Making a Graphical or Webserver Interface
4 Texas Hold'm Rules
5 Contact Information
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Chapter 0: Introduction
-----------------------
OOPoker, or "Object Oriented Poker", is a C++ No-Limit Texas Hold'm engine meant
to be used to implement poker AIs for entertainment or research purposes. These
AIs can be made to battle each other, or a single human can play against the AIs
for his/her enjoyment.
OOPoker is completely open source, it is licensed under GPL 3. It is hosted
here: https://github.com/lvandeve/oopoker
Currently only open source C++ code AIs are supported, it doesn't support play
over network or through encapsulated protocols at this time.
This program is intended mostly to be used by people who like programming, but
it's also possible to enjoy the program without programming by just running
it and playing against the built-in AIs.
This manual will explain two things:
-how to use the program to play
-how to program and use your own AIs
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Chapter 1: Terminology
----------------------
This chapter explains the terminology used both in the game and in the source
code.
Some terms can have multiple confusing meanings in Poker, especially "game", "hand", "bet" and "turn". For
that reason, some things are named differently here when possible, to avoid confusion.
Basically, a game of OOPoker is structured like this:
*) A Game = a complete tournament at 1 table. A game exists out of multiple Deals.
*) A Deal = dealing the cards. A Deal exists out of multiple Rounds.
*) A Round = pre-flop, flop, turn or river. A Round exists out of multiple Turns.
*) A Turn = one time going around the table while settling bets. Multiple turns occur if players keep raising. A Turn exists out of multipe Decisions.
*) A Decision = an action, one player making a decision during his turn.
Here's the full terminlogy list (alphabetically):
*) Action: choice a player can make: fold, check, call or raise.
*) All-in: action where you put so many chips on the table that your stack becomes empty. Sometimes
this is forced (e.g. when the blind was bigger than your stack).
*) Bet: an action where you raise when the call amount was 0. In OOPoker, usually the term
raise is used for the action that is normally called "bet" in poker, because mechanically,
"bet" and "raise" have the same effect. For example there's an action "A_RAISE" and an event "E_RAISE"
that take the role of both bet and raise.
If you need to distinguish bet and raise, keep track of the current call amount,
when it's 0, it's a bet instead of a raise.
However, in the PlayerStats statistics, "bets" and "raises" are separated.
To avoid confusion, amounts of chips aren't called "bet", but "wager" instead.
*) Betting Structure: information about the blinds, antes and buy-in amount at this table.
*) Big blind: the chip amount the big blind is, and, the player who is big blind during this deal.
*) Boast: This isn't a real poker term, but this term is used in OOPoker to indicate
you show your cards at the end of a deal when it wasn't required. So this is the opposite of "muck".
*) Call: action where you move the minimum required chips to not fold on the table.
*) Call Amount: amount of money you need to move from your stack to the table to call. This is the highest
wager on the table minus your current wager.
*) Check: action where you don't have to call and don't raise.
*) Chips: the money, or poker chips, played with.
*) Combination: a 5-card combination, that can form such a combination as full-house, pair, ...
A combination can be formed from 7 cards in Texas Hold'm, in that case the best possible
5-card combination is taken.
Also, the mathematical combination or binomial coefficient operation.
*) Deal: a single deal of cards and all that comes after it (flop, turn, river, showdown, if
the game doesn't end before that at least).
*) Dealer: the player who is dealer (or "the button") during this deal.
*) Decision: a player deciding what Action to do during his turn. Sometimes this is also just called "action", e.g. in the Statistics.
*) Deck: a complete deck of 52 cards.
*) Flop: the second round, when 3 cards are visible on the table.
*) Fold: action where you stop betting for this deal. You can't win the pot anymore.
*) Game: the term "game" refers to the game of poker in general, or this computer game, or the running
of the gameplay with Texas Hold'm rules. A game NEVER means a "deal" here, to avoid confusion.
A game can mean a complete tournament or a series of deals however.
*) Hand: the two cards you have in your hand
*) Hand card: a card you have in your hand
*) Lap: a lap of the dealer button, e.g. if there are 9 players this is 9 deals
*) Player: one person or AI playing.
*) Pot: the total amount of chips on the table during this deal so far. This is the sum of the bet of all players.
*) Stack: the amount of chips a certain player has.
*) Table: a table with a certain amount of players around it, who are playing poker.
*) Table card: card from the flop, turn or river on the table. Also called the board, or community cards.
*) turn (no caps): A turn of the players. In a turn, each player can choose to fold, raise, etc...
During a betting round, there can be multiple turns if players keep raising. Not to be confused with "TURN"!
*) TURN (caps): The Turn, that is, the 3rd round, when the 4th card on the table
becomes visible. Not to be confused with "turn"!
*) Round: AKA "betting round". There are maximum 4 betting rounds in a Deal: pre-flop,
flop, turn and river.
*) Pre-Flop: the first round, before any cards on the table are visible.
*) Pot: the sum of all wagers on the table.
*) Raise: action where the player bets extra money over the required call amount. The distinction
between "betting" and "raising" isn't really made in OOPoker, it's always called "raise".
*) Raise Amount: This terminology isn't from real poker, only relevant in OOPOker. It's the amount of
chips placed on top of the Call Amount, to raise. So basically in regular poker this is just
"the raise", but in OOPoker sometimes care must be taken if an amount of chips means the raise
amount above the call amount, or the total amount of chips you move to the table.
*) River: the 4th and last round, when the 5th card on the table becomes visible.
*) Showdown: when multiple players are still not folded after the river, they show
their cards to determine the winner with the best combination. The showdown stage
occurs after the river, only if multiple players are still active.
*) Small blind: the chip amount the small blind is, and, the player who is small blind during this deal.
*) Wager: The amount of chips that a player moved to the table (in the pot) during this deal so far. The
sum of all wagers, is the pot.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Chapter 2: Using the program
----------------------------
2.1 System Requirements
-----------------------
*) Works on most computers, no special graphics hardware or fastest processor is needed
*) Operating System: Windows or Linux
*) Free disk space when using the logger (it's enabled by default). When emulating
10000's of games, the log file tends to become quite big.
2.2 Gameplay
------------
The program currently works in a terminal window. When the program starts, a few
choices appear about the game type, the size of the buy-in, blinds, etc...
The game type choices are as follows:
*) human + AI's: play as human against multiple AI opponents
*) human + AI heads-up: play as human against a single AI opponent
*) AI battle: multiple AI's will play, at the end a winner will be declared. The human being can observe.
*) AI battle heads-up: two AI's will play against each other, at the end a winner will be declared. The human being can observe.
Next, you can choose a win condition, either the last
surviver at the table wins, or players can rebuy and there is a fixed amount of turns.
Due to the way the terminal input is programmed for this menu, you can hit keystrokes in a row to quickly
start a certain type of game. E.g. if you hit "3 2 1" in a row, an AI battle with 100 fixed rounds and
stacks of 1000 chips will start.
When you play as human, when it is your turn to make a decision, you simply have to
enter an amount of chips you move to the table. Depending on how much chips you move,
your action will be fold, check, call, bet/raise or all-in.
You don't have to explicetely choose "fold" or "check". Instead, for example when
the amount required to call is 50 chips, then when you'd enter 0, you'd fold,
when you'd enter 50, you'd call, and when you'd enter 200, you'd raise with 150.
While the game is running, at any time, you can press the "q" key, and it'll immediatly
stop (no confirmation is asked!!).
Sometimes you can enter "o" for an options menu. The options menu allows choosing
a delay between AI opponents. The delay allows following the game better, if there's
no delay, most AIs make a decision immediatly.
While playing, you see all events that happen, and whenever you can make a decision,
you see an ASCII-art representation of the table. Here's an example of a game in session
in the terminal:
> Player You calls.
> Player Laboes folds.
> Player Pimuve folds.
> Flop: 4c 6h Jh
> Player Heevapoe checks.
> Player Reeloehitry raises with 200.
> Player Faweel folds.
folded
Heevapoe Reeloehitry Faweel
$7600 $7400 $7600
##################################
### $2400 $2600 $2400 ###
folded ## ## folded
Vonhi ## ## Poero
$10000 ## O O P O K E R ## $10000
## 4c 6h Jh .. .. ##
folded (B) ## ##
Pimuve ## $200 ##
$9800 ## Qc Kh ##
### $100 $2400 ###
##################################
Laboes You
$9900 $7600
folded (S) Current (D)
chip amount (200 to call, q to quit, o for options):
At any time during the game, even if the program isn't awaiting terminal input,
you can hit the "q" key to immediatly stop the game.
2.3 Battling AIs
----------------
You can make AIs play against each other without human involvement. This is called
an "AI Battle". You can test how good or bad your AI's are compared to other AI's by
making them play against each other this way.
There are different ways to score the AIs: either the last survivor wins (and no
rebuys are allowed), or rebuys are allowed and the AI who won the most money after
a fixed amount of turns wins. The larger you set this fixed amount of turns, the
more precise you can determinate which AI is the smartest (but it takes a longer
time to run).
At the end you can see which AIs won, and their statistics.
2.4 Player Statistics
---------------------
At the end of a game, you might see some player statistics like this:
Player Stats for Nekana, AI: Smart
General: deals: 1000 actions: 1822 preflop actions: 1172
Rounds Seen: flops: 247 turns: 206 rivers: 170 showdowns: 140
Wins: total: 93 showdown: 72 bluff: 21
Chips: won: 148221 lost: 199272 bought: 7000 forced bets: 1500
Pre-Flop Stats: VP$IP: 0.306 PFR: 0.083 3Bet: 0.081
Post-Flop Stats: AF: 1.41667 WSD: 0.14 WSDW: 0.072
The meaning of some of the values are:
*Pre-Flop*
VP$IP, VPIP: Percentage: Voluntary Put Money In Pot:
Tight: Less than 0.24
Neutral: Between 0.24-0.3
Loose: Greater than 0.3
PFR: Pre-Flop Raise percentage: percentage of bets or raises before the flop, percentage given in range 0.0-1.0
Passive: less than 1/4th of VPIP
Agressive: more than 1/4th of VPIP
Pre-Flop 3Bet percentage: percentage of reraises before the flop, percentage given in range 0.0-1.0
*Post-Flop*
AF: Aggression Factor after the flop:
Passive: Less than 1.5
Neutral: Between 1-1.5
Aggressive: Greater than 1.5
WSD: Went to ShowDown percentage, percentage given in range 0.0-1.0 (calculated as showdowns_seen / flops_seen)
Solid: less than 0.39 (A value of good players is 0.25)
Overplaying cards: Greater than 0.39
WSDW: Went to ShowDown and Won, percentage given in range 0.0-1.0
This is the amount of showdowns won (including split pots) divided through the total amount of showdowns seen.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Chapter 3: Programming AIs
--------------------------
This chapter will explain how to program your own OOPoker AIs, in C++.
Depending on your knowledge, you may be able to skip certain sections.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Section 3.1: Really Quickly Getting Started
-------------------------------------------
How to get the game working and have your own AI in it:
*) Get a C++ compiler and IDE.
Try Code::Blocks (http://www.codeblocks.org/), or see next sections.
Get the version WITH Mingw compiler included!
*) Set up your C++ project with the OOPoker source files, set the right project settings
With Code::Blocks, just open the file OOPoker.cbp, it should have all project settings ready.
*) Compile and run OOPoker, try out the game.
With Code::blocks, press F9 and it should compile and run the project.
*) Now to program your own AI:
*) Copy the files "ai_smart.cpp" and "ai_smart.h", and name your copies "ai_my_bot.cpp"
and "ai_my_bot.h".
*) Include these files in your C++ project.
*) In both files, rename all instances of "AISmart" to "AIMyBot".
*) In main.cpp, type #include "ai_my_bot.h" at the beginning of the file near all other #includes.
*) In main.cpp, search for the function "void doGame()", and there find the part that says
"else if(gameType == 2) //Human + AI heads-up"
There, replace
game.addPlayer(Player(new AISmart(), getRandomName()));
into
game.addPlayer(Player(new AIMyBot(), getRandomName()));
*) The above changes "Human + AI heads-up". It's similar for the other game modes.
*) Implement the functions in the ai_my_bot.cpp files with your own AI specific code (replacing
or modifying the existing code of the copeid AISmart AI).
*) Look at the implementation of other AIs such as ai_smart.cpp, ai_checkfold.cpp, etc...
to learn about the C++ syntax.
*) You can use utility functions in the class Info, or utility methods from combination.h,
pokermath.h, random.h and util.h to help implementing your AI, or roll your own poker
math, databases, etc... to control your AI.
*) Look in the comments of the OOPoker code to learn the API of classes or headers and what
the purpose and usage of some classes or function is!
*) Look in the rest of this guide to learn more about C++, the API of OOPoker, tips, etc...
*) Then start the game, choose "Human + AI heads-up", and you can play against your AI!
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Section 3.2 C++, Compiler and IDE.
----------------------------------
3.2.1 C++
---------
OOPoker uses C++. If you don't know how to use this programming language, this
chapter will help you on your way. There are some example AIs provided, so even
if you've never used C++ before, the code in these AIs might help you on your
way to learn the syntax!
First of all, place all the code of OOPoker (all the .cpp and .h files, and this
readme.txt file) in a directory.
3.2.2 Compiler
--------------
To begin programming, you'll need a C++ compiler, and an IDE or text editor
to write the code.
On Windows, you can use Code::Blocks, Visual Studio Express, or if all else fails, Dev-C++.
In these programs, you need to create a new C++ project, and then include all
the .cpp and .h files from OOPoker in your project. Then find the "compile" button
to compile the source, then find the "run" or "debug" button to run OOPoker.
A Code::Blocks project file (OOPoker.cbp) is provided so you can immediatly
get started if you use Code::Blocks: just open the project file, hit F9, and the
game compiles and runs.
When downloading Code::Blocks, get the version WITH Mingw compiler included, unless
you have a reason to choose a different compiler and tweak the Code::Blocks settings for that.
In Linux, this is very easy, there are plenty of text editors that can open
multiple source files (geany, Kate, gedit, ...), and the compiler is usually
built right in your OS (it's the g++ command), or easy to install with your
package manager (install gcc). To compile OOPoker, just go with your terminal
to the folder with the OOPoker code, and type "g++ *.cpp -W -Wall -Wextra -ansi".
After that, type ./a.out and OOPoker will run.
3.2.3 Language
--------------
Once you've managed to compile and run OOPoker, here's some information about
what you'll need to know about C++ to make AIs:
-the general syntax of C++ is similar to that of C, Java, C#, and other curly-brace
languages. If you've never used such a language before, try to look at the implementation
of the example AI's.
-A few typical concepts of C++ are required to program for OOPoker:
*) Headers and source files: C++ uses source files (.cpp) and header files (.h).
Typicall, in header files, you declare functions and classes, while in source
files you implement the actual code. This is why every OOPoker AI has two files,
for example "ai_call.cpp" and "ai_call.h".
*) Object Oriented programming: OOPoker AI's are object oriented, that is, they
all must inherit from the class "AI" or "AINamed" and implement a few functions
(explained later on).
*) struct <--> class: a struct and a class are exactly the same thing in C++,
except one little detail: in a class, members are private by default (until
you type "public:" somewhere, while in a struct, members are public by default
(until you type "privete: " somewhere). Good practice indicates to use classes
for true object-oriented programming, but to use structs for just grouping a few
variables together. OOPoker uses structs quite a lot, even in a few situations where
a class might have been more approriate. Sorry for that.
*) std::string: text strings. For a description of its functions,
please look here:
http://www.cppreference.com/wiki/string/start
*) std::vector<T>: a dynamic array type. For a description of its functions,
please look here:
http://www.cppreference.com/wiki/stl/vector/start
For the rest, if you've never used C++ before, I recommend you to follow the
steps of the "Really Quickly Getting Started" chapter.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Section 3.3: Implementing the AI
--------------------------------
The functions of class AI in ai.h have to be implemented in your class.
For implementing the AI, the most important function to implement is doTurn, because
that is where the decision is taken to fold, check, call, bet/raise or go all-in. Here's the
purpose of each function.
The manual below gives a rough description of functions, classes and structs. For exact
information about each value, member, etc..., please see the comments in the source code (e.g.
the commenfs of Action are in action.h, etc...).
*) virtual Action doTurn(const Info& info) = 0;
Make a decision for this turn: fold, check, call or raise? The output
of this function is an Action, the input is an Info.
The Action contains an enumeration indicating the type of action: FOLD, CHECK, CALL
or RAISE. Bet and raise are considered the same. All-in can be reached with both a
CALL and a RAISE action depending on your stack. Furthermore, the Action contains
a value, which is used only for the RAISE action. This value is the amount of money
you move from your stack to the table. It is NOT the amount you raise! It's the
amount you raise plus the call amount.
The Info contains all information you have available during this turn. That is:
your cards, the table cards if any, showdown cards if any, the index of you, the dealer,
everyone's stack and bet, the pot, the betting structure, the current round, the
amount of turns this round, the name of each player.
*) virtual void onEvent(const Event& event);
This function gives the same information as you get from the Info in doTurn, but
in a different format and sometimes some extra information. For example, if you're
all in or folded you can't make decisions anymore and thus get no more Info from doTurn,
but you still get the events.
An event is something like "a player calls", "a player quits", "the flop happened and
has those 3 cards", and so on. This is really linear, and in the correct order. You're not
required to implement this function for your AI. But you can implement it to remember events
and base decisions you'll do later in doTurn on this.
*) bool boastCards(const Info& info);
Called at the end of a deal, only if this AI wasn't required to show his cards.
Based on the info you can decide to show your cards or not. You can for example
decide to show them to prove you were not bluffing, or decide to not show them
to hide your playing style.
*) virtual std::string getAIName() = 0;
Return a unique name for your AI here. That way, when an AI battle occurs, you
can see which AI won. The AI name is not the same as a player's name. Multiple
players can have the same AI, those players will have a different name, but the
same AI name.
NOTE: AI's will never get the AI-name of other players, only their player name,
except completely at the end of the game when the rankings are provided.
So AI's normally don't know which implementation another player has as AI. The AI
can only learn the style of a player during a game by observing their behaviour.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Section 3.4: Putting your AI in the game
----------------------------------------
Putting your AI in the game is done by adjusting the code in main.cpp. The in-game
options don't allow choosing AI's, instead you choose them in the C++ code, compile
the program, and then let the AI's battle. To change which AI's battle, change the C++
code again with the different AI's and start the game again. This allows the most
flexibility, and compiling this program doesn't take long.
See also Really Quickly Getting Started for some information about this, the final
steps describe exactly where in main.cpp to change something.
This chapter gives some info for the programmer who wants to do a little more.
To put your AI in the game, you have to create the Game instance and add
your AI to it with the addPlayer method. This is all already done in main.cpp.
In main.cpp, there's a part in the code where it'll add some players to the game
depending on which choice you made for "game type" in the in-game menu. For each
game type, you can change the AI's that are added to the game in the code. You can
also completely change everything in main.cpp if you want, to remove the menu and
just set up the game completely from within the code, including the betting
structure and so on.
In the "stock" main.cpp, all players get a random name with "getRandomName()". If
you don't like this, you can just use a fixed string there instead. If you want
to recognise which AI won, though, you don't need this player name. The name of the AI
itself is normally given in the log events and terminal output, so it shouldn't matter
that the player using your AI has a random name.
Once you finished this, you can start tournaments, e.g. try a AI battle heads-up of
your AI against AISmart. If your AI wins most of the time, it's a good AI!
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Section 3.5: Utility Functions
------------------------------
For implementing your AI, several utility methods are availabe. You are however
encouraged to create your own utility functions and poker algorithms in your AI
instead of only using the ones provided!
Useful utility methods are in the following classes and/or header files.
*) class Info from info.h (this is what you get in doTurn)
Has utility methods for simple things such as getting the total pot on the table,
the highest bet of a player, getting the amount of players that didn't fold yet, etc...
It has also got the "getMRatio()" function, which returns (your stack) / (small blind + big blind + total antes)
*) functions in pokermath.h
This has a mix of functions for various purposes.
getSklanskyMalmuthGroup and getRealPlayStatisticsEV can help deciding whether your cards are good or not (see
the description in pokermath.cpp in the implementation of these functions for more details).
isPair, isSuited, isConnector are handy for some more decisions about your hand cards.
splitIntoSuits, getAmountPerSuit can only be used for slow calculations similar to combination.h
eval7, eval7_index, eval5, eval5_index are very good functions for similating thousands of hands, see the section
"Fast Evaluation" for more information.
getWinChanceAgainst1AtFlop etc... use eval7 to calculate the win chance at flop, turn and river, simulating
every possible combination of extra table cards and hand cards of one opponent. This doesn't use random, it
tries every possible combination, which turns out to go fast enough with eval7.
*) functions in combination.h
the classes and functions in combination.h are a "naive" combination evaluator. For simulation work, use
eval7 in pokermath.h instead.
The naive methods here are useful for getting a nice name of a combination, finding out exactly which cards
are part of a combination, ...
*) random.h
This contains the function getRandom(), which returns a random value in the range 0.0-1.0, as well as some
functions for other possible return value ranges.
This random value is a non-blocking true random. It uses the randomness facilities of your
operating system. Usually (on Linux and Windows) this includes some random data from mouse movement,
network activity, etc... It is non-blocking, which means that if no true random data is available,
a semi-random-number generator is used instead.
Furthermore it contains getRandomFast(), which uses a very simple, but fast, pseudo random number generator.
There are some methods to seed it with true random values now and then.
getRandomFast() should be used when doing monte-carlo simulations of cards to calculate win equity, because getRandom() is too slow
to do even as little as 10000 random hand evaluations in a reasonable time.
*) card.h
Get the suit, value or an index of a card.
The value is 2-14. The ace has value 14 instead of 1 so that it's the highest.
The index value is currently not really used in OOPoker. Also, every poker and card
game has their own index system for cards, this is just yet another one. The values are:
unknown : -1
clubs : 0=ace, 1=2, 2=3, 3=4, 4=5, 5=6, 6=7, 7=8, 8=9, 9=T, 10=J, 11=Q, 12=K
diamonds: 13=ace, 14=2, 15=3, 16=4, 17=5, 18=6, 19=7, 20=8, 21=9, 22=T, 23=J, 24=Q, 25=K
hearts : 26=ace, 27=2, 28=3, 29=4, 30=5, 31=6, 32=7, 33=8, 34=9, 35=T, 36=J, 37=Q, 38=K
spades : 39=ace, 40=2, 41=3, 42=4, 43=5, 44=6, 45=7, 46=8, 47=9, 48=T, 49=J, 50=Q, 51=K
*) util.h
A small amount of extra utility functions, to convert strings from/to text more easily than C++'s stringstreams,
"wrap" a number or get a nice rounded number near a given number (e.g. turning 69907 into 50000)
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Section 3.6: Fast Evaluation (For Win Equity)
---------------------------------------------
Sometimes poker AIs use simulations to calculate their odds. For simulations,
many possible 7-card combinations need to be checked and compared.
To be able to do as many evaluations as possible, it's preferrable to be able
to simulate thousands or millions of hands per second.
That is what eval5 and eval7 can be used for. These use the evaluators
developed by Cactus Kev, and by pokerai.org forum. It are amongst the
fastest evaluators avaible. All credit goes to these guys:
Cactus Kev (http://www.suffecool.net/poker/evaluator.html)
XPokerEval (http://www.codingthewheel.com/archives/poker-hand-evaluator-roundup)
2+2 poker forums (http://archives1.twoplustwo.com/showflat.php?Number=8513906)
mykey1961
pokercurious
Unless you found a faster one, you can use these functions for your AI if you
need to evaluate many hands.
Whenever you're tempted to use functions from combination.h and do multiple calls
to "combinationGreater", then use eval5 or eval7 instead. It is easily
1000 times faster.
Both eval5 and eval7 get cards as parameter, and return an integer.
If you call eval7 twice with different cards, and the integer returned by one call
is greater than the other, the cards of the greatest integer form a better combination
than the others.
Same for eval5.
Integer values returned by eval5 and eval7 may not be compared to each other, they use a different system.
The cards given as parameter for eval7 must be converted to an integer using eval7_index (do NOT use Card.getIndex()).
The cards given as parameter for eval5 must be converted to an integer using eval5_index (do NOT use Card.getIndex()).
This is because each algorithm uses its own specific, different, integer format for cards.
The implementation of getWinChanceAgainst1AtFlop demonstrates how to use eval7.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Section 3.7: OOPoker Code Overview
----------------------------------
This section gives an overview of all the source code files of OOPoker. Not everything
of this is needed to implement your poker AI, because many source files are used for
running the game instead.
The order is alphabetical.
*) action.cpp, action.h
This is an action, the result of a doTurn call of an AI (fold, check, call, raise, and how much?)
*) ai.cpp, ai.h
This is the interface of the AI class you can implement
NOTE: a bit counter-intuitive, human players are also implemented using an AI. It's just an AI that
asks a human what to do through the user interface, instead of an AI that calculates it on its own then.
*) ai_blindlimp.cpp, ai_blindlimp.h
Very naive demo AI. This one calls blinds, then check-folds.
*) ai_call.cpp, ai_call.h
Very naive demo AI. It always calls.
*) ai_checkfold.cpp, ai_checkfold.h
Very naive demo AI. It always check-folds.
*) ai_human.cpp, ai_human.h
This isn't really an AI, it's the human player instead. This class is interesting
to look at, because it implements the AI in a different way, namely it asks
the human sitting in front of the computer what to do instead of calculating it
on its own. It also prints the information in the terminal for the human to read.
It has also got a timer implemented that can pause for half a second at every event,
to allow emulating gameplay where players think a while, otherwise everything goes
way too fast.
*) ai_raise.cpp, ai_raise.h
Very naive demo AI. It always raises, unless too much turns
passed (otherwise they'd keep raising forever, preventing the next round to start).
*) ai_random.cpp, ai_random.h
Very naive demo AI. It always does a random action. It has the potention to randomly
do something very good, or something very bad.
*) ai_smart.cpp, ai_smart.h
The most interesting demo AI. It uses some poker math and card evaluation to
make decisions. However, it still isn't that very smart, it's only smart compared
to the very naive demo AI's.
The intention is that you program a better AI than AISmart!
*) card.cpp, card.h
The Card class.
*) changelist.h
Lists recent enhancements and bugfixes. Also mentions incompatible changes,
that require making a few changes to existing bots to let them compile against
OOPoker again.
*) combination.cpp, combination.h
The combination class and functions to do slow but "nice" combination evaluation.
*) deck.cpp, deck.h
A deck of cards. This can be randomly shuffled, and then cards taken from the top.
Used to run the game. The randomness from random.h is used.
*) event.cpp, event.h
The Event struct, that can be sent to every player to give information about the game.
*) game.cpp, game.h
In these source files, the actual gameplay is implemented, this handles the betting rounds,
choosing the next dealer, pot division, etc... according to the rules of Texas Hold'm.
Could also contain a few utility functions useful to AIs, such as checking how will the pot be
divided amongst players depending on who would have the best cards.
The header file also contains a few general enums and structs, such as Round and Rules.
*) host.cpp, host.h
The host runs the game. This class has some power like deciding when to quit the game.
*) host_terminal.cpp, host_terminal.h
Implementation of host in the terminal. Draws a table representation now and then, and,
allows pressing "q" at any time to quit the game, even while AI's are working.
*) info.cpp, info.h
The Info struct, that can be used by AI's in doTurn to get current information.
*) io_terminal.cpp, io_terminal.h
Utility functions to use the terminal in Windows and Linux, draw the poker table
in ASCII-art, etc..., for the user interface.
*) main.cpp, main.h
This contains the main function that starts the program and sets up the game.
This is where you can insert your AI's to the game. See section
"Really Quickly Getting Started" for more information about this.
*) observer.cpp, observer.h
Apart from players, there can also be observers at the table. These don't play the game,
but receive events about what is happening. There are two implementations of the observer
interface: observer_terminal (terminal output) and observer_log (log file output)
*) observer_statkeeper.cpp, observer_statkeeper.h
Observer that updates a StatKeeper (see statistics.h). Used internally by the Game to
update statistics of players.
*) observer_terminal.cpp, observer_terminal.h
This observer is used in the AI Battle modes, so that you can see what the AIs are doing.
*) observer_terminal_quiet.cpp, observer_terminal_quiet.h
Very similar to observer_terminal, but shows less events, causing the game to possibly
run faster.
*) observer_log.cpp, observer_log.h
This observer is used in all game types. It appends all events to a file "log.txt". This
allows seeing the history of all games ever. Since it appends, the file will become bigger
and bigger, so delete it if you don't need it anymore.
*) player.cpp, player.h
Information about players (such as their stack, AI, etc...). Used to run the game.
Not accessible by poker AI's, they get this information in the Info struct instead.
*) pokereval.cpp, pokereval.h
This is the code made by Cactus Kev and 2+2 poker forums for fast poker hand evaluation, but
the OOPoker interface for this is actually in pokermath.h.
*) pokereval2.cpp, pokereval2.h
This is code I found later. It's faster than pokereval.cpp and doesn't use a handranks.dat file. So
the 7-card evaluator from pokereval.cpp is made obsolete (but its 5-card evaluator is still used).
The OOPoker interface for this is actually in pokermath.h.
*) pokermath.cpp, pokermath.h
Utility functions for poker AI's.
*) random.cpp, random.h
Getting an almost random number. Used both for running the game (shuffling the card
deck) and some AI's (making unpredictable decisions). Slightly more true-random
than C's "rand()".
*) rules.cpp, rules.h
Contains a struct with the current game rules (blind values, win condition, ...).
Also contains the Round enum (not really a rule, but it fit the best here).
*) statistics.cpp, statistics.h
This contains a struct with player statistics, and a StatKeeper that can update
stats based on the game events. This is used by the game to provide player statistics
at the end, but it can also be used by your AI to keep track of players if you wish so.
To use it in your AI, you have to make your own StatKeeper object and forward all events
you receive in onEvent to the StatKeeper.
If you need more statistics about players than this for your AI, implement a different
StatKeeper in different source files, since those from statistics.h are standard for the
game itself and thus supposed to stay as they are.
StatKeeper is also a good demonstration of getting information about the game from
events.
*) table.cpp, table.h
Information about the table, such as who is sitting on it. Used to run the game.
Not accessible by poker AI's, they get this information in the Info struct instead.
*) unittest.cpp, unittest.h
This are unit tests to validate OOPoker, especially to check if it runs the game
correctly according to the Texas Hold'm rules.
NOTE: good unit tests work automatically, and say at the end how many errors were found.
The unit test of OOPoker currently doesn't report errors, it only gives output that
requires human inspection to validate its correctness!
*) util.cpp, util.h
A small amount of extra utility functions, to convert strings from/to text more easily than C++'s stringstreams,
"wrap" a number or get a nice rounded number near a given number (e.g. turning 69907 into 50000)
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Section 3.8: Making a Graphical or Webserver Interface
------------------------------------------------------
OOPoker is currently only implemented to work in the console. This is because so
far the program focuses on the math and poker rules, instead of on the user interface.
However, it is possible to make a graphical client, or webserver version that can be
played in a browser, without doing too radical changes:
What has to be done is to create an implementation of the classes Host, AI and Observer
that interact using the alternativ einterface rather than with the console. Those 3 classes
will also need to work together a bit, because they use the same input and output channels.
For the terminal version of OOPoker, the clases HostTerminal, AIHuman and ObserverTerminal
all use the console.
If you implement graphical or webserver versions of these, then you can plug in those
into the Game instead of the terminal ones.
Apart from making these 3 classes, the main function itself from main.cpp also has to be changed,
currently it uses the terminal to ask what type of game to play.
Note that OOPoker's terminal implementation is designed to work on both Windows and Linux. Other
interfaces should preferably also be multi-platform.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Chapter 4: Texas Hold'm Rules
-----------------------------
OOPoker uses fairly standard Texas Hold'm rules. The points below are just a few
clarifications. Extra features (such as increasing blind and limit games) might
be added to OOPoker later.
*) It's no-limit texas hold'm, so raises can be as big as you want
*) When raising, the raise amount must be at least as big as the previous raise
amount (initially this is the big blind)
*) Apart from the small blind and big blind, an optional ante can be configured.
*) Tournaments are currently always at a single table, with two possible win conditions:
-the last surviver
-the one who earned most money after a fixed amount of deals with rebuys
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Chapter 5: Contact Information
------------------------------
Feel free to contact me for requests related to OOPoker.
My name is at the bottom of the copyright message. My email address is first name
dot last name at gmail dot com.