forked from rggibson/open-pure-cfr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
card_abstraction.cpp
163 lines (143 loc) · 3.92 KB
/
card_abstraction.cpp
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
/* card_abstraction.cpp
* Richard Gibson, Jun 28, 2013
*
* Home of the card_abstraction abstract class and all implementing classes
*
* Copyright (C) 2013 by Richard Gibson
*/
/* C / C++ / STL indluces */
/* project_acpc_server includes */
extern "C" {
}
/* Pure CFR includes */
#include "card_abstraction.hpp"
CardAbstraction::CardAbstraction( )
{
}
CardAbstraction::~CardAbstraction( )
{
}
/* By default, assume cannot precompute buckets */
void CardAbstraction::precompute_buckets( const Game *game, hand_t &hand ) const
{
fprintf( stderr, "precompute_buckets called for base "
"card abstraction class!\n" );
assert( false );
}
NullCardAbstraction::NullCardAbstraction( const Game *game )
: deck_size( game->numSuits * game->numRanks )
{
/* Precompute number of buckets per round */
m_num_buckets[ 0 ] = 1;
for( int i = 0; i < game->numHoleCards; ++i ) {
m_num_buckets[ 0 ] *= deck_size;
}
for( int r = 0; r < MAX_ROUNDS; ++r ) {
if( r < game->numRounds ) {
if( r > 0 ) {
m_num_buckets[ r ] = m_num_buckets[ r - 1 ];
}
for( int i = 0; i < game->numBoardCards[ r ]; ++i ) {
m_num_buckets[ r ] *= deck_size;
}
} else {
m_num_buckets[ r ] = 0;
}
}
}
NullCardAbstraction::~NullCardAbstraction( )
{
}
int NullCardAbstraction::num_buckets( const Game *game,
const BettingNode *node ) const
{
return m_num_buckets[ node->get_round() ];
}
int NullCardAbstraction::num_buckets( const Game *game,
const State &state ) const
{
return m_num_buckets[ state.round ];
}
int NullCardAbstraction::get_bucket( const Game *game,
const BettingNode *node,
const uint8_t board_cards[ MAX_BOARD_CARDS ],
const uint8_t hole_cards
[ MAX_PURE_CFR_PLAYERS ]
[ MAX_HOLE_CARDS ] ) const
{
return get_bucket_internal( game, board_cards, hole_cards,
node->get_player(), node->get_round() );
}
void NullCardAbstraction::precompute_buckets( const Game *game,
hand_t &hand ) const
{
for( int p = 0; p < game->numPlayers; ++p ) {
for( int r = 0; r < game->numRounds; ++r ) {
hand.precomputed_buckets[ p ][ r ] = get_bucket_internal( game,
hand.board_cards,
hand.hole_cards,
p, r );
}
}
}
int NullCardAbstraction::get_bucket_internal( const Game *game,
const uint8_t board_cards
[ MAX_BOARD_CARDS ],
const uint8_t hole_cards
[ MAX_PURE_CFR_PLAYERS ]
[ MAX_HOLE_CARDS ],
const int player,
const int round ) const
{
/* Calculate the unique bucket number for this hand */
int bucket = 0;
for( int i = 0; i < game->numHoleCards; ++i ) {
if( i > 0 ) {
bucket *= deck_size;
}
uint8_t card = hole_cards[ player ][ i ];
bucket += rankOfCard( card ) * game->numSuits + suitOfCard( card );
}
for( int r = 0; r <= round; ++r ) {
for( int i = bcStart( game, r ); i < sumBoardCards( game, r ); ++i ) {
bucket *= deck_size;
uint8_t card = board_cards[ i ];
bucket += rankOfCard( card ) * game->numSuits + suitOfCard( card );
}
}
return bucket;
}
BlindCardAbstraction::BlindCardAbstraction( )
{
}
BlindCardAbstraction::~BlindCardAbstraction( )
{
}
int BlindCardAbstraction::num_buckets( const Game *game,
const BettingNode *node ) const
{
return 1;
}
int BlindCardAbstraction::num_buckets( const Game *game,
const State &state ) const
{
return 1;
}
int BlindCardAbstraction::get_bucket( const Game *game,
const BettingNode *node,
const uint8_t board_cards
[ MAX_BOARD_CARDS ],
const uint8_t hole_cards
[ MAX_PURE_CFR_PLAYERS ]
[ MAX_HOLE_CARDS ] ) const
{
return 0;
}
void BlindCardAbstraction::precompute_buckets( const Game *game, hand_t &hand ) const
{
for( int p = 0; p < game->numPlayers; ++p ) {
for( int r = 0; r < game->numRounds; ++r ) {
hand.precomputed_buckets[ p ][ r ] = 0;
}
}
}