src/canonical_cards.cpp
// Code liberally borrowed from CFR+ implementation from University of
// Alberta.
// Assumes cards are sorted by rank
// Currently only supports adding N cards to nothing.
Code liberally borrowed from CFR+ implementation from University of
Alberta.
Assumes cards are sorted by rank
Currently only supports adding N cards to nothing.
Code liberally borrowed from CFR + implementation from University of Alberta . Assumes cards are sorted by rank Currently only supports adding N cards to nothing .
int CanonicalCards::NumMappings(const Card *cards, int num_cards, int old_suit_groups) {
  int group_used[4], suit_used[4], group_size[4];
  int num_suits = Game::NumSuits();
  int new_suit_groups = old_suit_groups;
  for (int s = 0; s < num_suits; ++s) group_size[s] = 0;
  for (int s = 0; s < num_suits; ++s) {
    ++group_size[((unsigned char *)&new_suit_groups)[s]];
  }
  int start = 0;
  int num_mappings = 1;
  while (start < num_cards) {
    for (int s = 0; s < num_suits; ++s) {
      group_used[s] = 0;
      suit_used[s] = 0;
    }
    int start_rank = Rank(cards[start]);
    int end = start;
    do {
      Card c = cards[end];
      int s = Suit(c);
      ++suit_used[s];
      ++group_used[((unsigned char *)&new_suit_groups)[s]];
      ++end;
    } while (end < num_cards && Rank(cards[end]) == start_rank);
    for (int g = 0; g < num_suits; ++g) {
      int gu = group_used[g];
      if (gu == 0) continue;
      num_mappings *= NChooseK(group_size[g], gu);
      int t = group_size[g];
      group_size[g] = group_used[g];
      int s = g;
      while (1) {
	if (! suit_used[s]) {
	  return 0;
	}
	if (! --group_used[g]) {
	  break;
	}
	while (((unsigned char *)&new_suit_groups)[++s] != g);
      }
      for (++s; s != num_suits; ++s) {
	if (((unsigned char *)&new_suit_groups)[s] == g ) {
	  ((unsigned char *)&new_suit_groups)[s] = s;
	  group_size[s] = t - group_size[g];
	  t = s;
	  for (++s; s != num_suits; ++s) {
	    if (((unsigned char *)&new_suit_groups)[s] == g) {
	      ((unsigned char *)&new_suit_groups)[s] = t;
	    }
	  }
	  break;
	}
      }
    }
    start = end;
  }
  return num_mappings;
}
int CanonicalCards :: NumMappings ( const Card * cards , int num_cards , int old_suit_groups ) { int group_used [ 4 ] , suit_used [ 4 ] , group_size [ 4 ] ; int num_suits = Game :: NumSuits ( ) ; int new_suit_groups = old_suit_groups ; for ( int s = 0 ; s < num_suits ; ++ s ) group_size [ s ] = 0 ; for ( int s = 0 ; s < num_suits ; ++ s ) { ++ group_size [ ( ( unsigned char * ) & new_suit_groups ) [ s ] ] ; } int start = 0 ; int num_mappings = 1 ; while ( start < num_cards ) { for ( int s = 0 ; s < num_suits ; ++ s ) { group_used [ s ] = 0 ; suit_used [ s ] = 0 ; } int start_rank = Rank ( cards [ start ] ) ; int end = start ; do { Card c = cards [ end ] ; int s = Suit ( c ) ; ++ suit_used [ s ] ; ++ group_used [ ( ( unsigned char * ) & new_suit_groups ) [ s ] ] ; ++ end ; } while ( end < num_cards && Rank ( cards [ end ] ) == start_rank ) ; for ( int g = 0 ; g < num_suits ; ++ g ) { int gu = group_used [ g ] ; if ( gu == 0 ) continue ; num_mappings *= NChooseK ( group_size [ g ] , gu ) ; int t = group_size [ g ] ; group_size [ g ] = group_used [ g ] ; int s = g ; while ( 1 ) { if ( ! suit_used [ s ] ) { return 0 ; } if ( ! -- group_used [ g ] ) { break ; } while ( ( ( unsigned char * ) & new_suit_groups ) [ ++ s ] != g ) ; } for ( ++ s ; s != num_suits ; ++ s ) { if ( ( ( unsigned char * ) & new_suit_groups ) [ s ] == g ) { ( ( unsigned char * ) & new_suit_groups ) [ s ] = s ; group_size [ s ] = t - group_size [ g ] ; t = s ; for ( ++ s ; s != num_suits ; ++ s ) { if ( ( ( unsigned char * ) & new_suit_groups ) [ s ] == g ) { ( ( unsigned char * ) & new_suit_groups ) [ s ] = t ; } } break ; } } } start = end ; } return num_mappings ; }
Code liberally borrowed from CFR+ implementation from University of
Alberta.
Code liberally borrowed from CFR + implementation from University of Alberta .
// Start with all suits in group 0 // group_size starts out with the number of cards in each group, // calculated over all of the input cards. // Each time through this loop we consume a sequence of cards with the // same rank.  group_used[g] is the number of cards in the sequence // with group g.  suit_used[s] is the number of cards in the sequence // with suit s. /* start updating group_size array */ /* check that the smallest valued cards are chosen for each group */ // cards don't use the lowest valued suits - not canonical /* finish updating the grouping information */