src/eval_node.cpp
// Compute outcome from B's perspective
Compute outcome from B's perspective
Compute outcome from B ' s perspective
void Player::Showdown(Node *a_node, Node *b_node, shared_ptr<double []> *reach_probs,
		      const string &action_sequence) {
  Card max_card1 = Game::MaxCard() + 1;
  double *a_probs = b_pos_ == 0 ? reach_probs[1].get() : reach_probs[0].get();
  double *b_probs = b_pos_ == 0 ? reach_probs[0].get() : reach_probs[1].get();
  unique_ptr<double []> cum_opp_card_probs(new double[52]);
  unique_ptr<double []> total_opp_card_probs(new double[52]);
  for (Card c = 0; c < max_card1; ++c) {
    cum_opp_card_probs[c] = 0;
    total_opp_card_probs[c] = 0;
  }
  int max_street = Game::MaxStreet();
  int num_hole_card_pairs = Game::NumHoleCardPairs(max_street);
  double sum_opp_probs = 0;
  for (int hcp = 0; hcp < num_hole_card_pairs; ++hcp) {
    const Card *cards = hands_->Cards(hcp);
    Card hi = cards[0];
    Card lo = cards[1];
    int enc = hi * max_card1 + lo;
    double opp_prob = a_probs[enc];
    total_opp_card_probs[hi] += opp_prob;
    total_opp_card_probs[lo] += opp_prob;
    sum_opp_probs += opp_prob;
    if (opp_prob > 1.0) {
      fprintf(stderr, "Showdown: opp_prob (a) %f hcp %u\n", opp_prob, hcp);
      exit(-1);
    }
  }
#if 0
  if (action_sequence == target_action_sequence_ && msbd_ == 11 && b_pos_ == 1) {
    for (int i = 0; i < num_hole_card_pairs; ++i) {
      const Card *cards = hands_->Cards(i);
      Card hi = cards[0];
      Card lo = cards[1];
      int enc = hi * max_card1 + lo;
      OutputTwoCards(hi, lo);
      printf(" %f (%i)\n", reach_probs[1][enc], i);
      fflush(stdout);
    }
  }
#endif
  double opp_cum_prob = 0;
  unique_ptr<double []> win_probs(new double[num_hole_card_pairs]);
  double half_pot = a_node->LastBetTo();
  double sum_our_vals = 0, sum_joint_probs = 0;
  int j = 0;
  while (j < num_hole_card_pairs) {
    int last_hand_val = hands_->HandValue(j);
    int begin_range = j;
    while (j < num_hole_card_pairs) {
      const Card *cards = hands_->Cards(j);
      Card hi = cards[0];
      Card lo = cards[1];
      int hand_val = hands_->HandValue(j);
      if (hand_val != last_hand_val) break;
      win_probs[j] = opp_cum_prob - cum_opp_card_probs[hi] - cum_opp_card_probs[lo];
      ++j;
    }
    for (int k = begin_range; k < j; ++k) {
      const Card *cards = hands_->Cards(k);
      Card hi = cards[0];
      Card lo = cards[1];
      int enc = hi * max_card1 + lo;
      double opp_prob = a_probs[enc];
      if (opp_prob <= 0) continue;
      cum_opp_card_probs[hi] += opp_prob;
      cum_opp_card_probs[lo] += opp_prob;
      opp_cum_prob += opp_prob;
    }
    for (int k = begin_range; k < j; ++k) {
      const Card *cards = hands_->Cards(k);
      Card hi = cards[0];
      Card lo = cards[1];
      int enc = hi * max_card1 + lo;
      double our_prob = b_probs[enc];
      double better_hi_prob = total_opp_card_probs[hi] - cum_opp_card_probs[hi];
      double better_lo_prob = total_opp_card_probs[lo] - cum_opp_card_probs[lo];
      double lose_prob = (sum_opp_probs - opp_cum_prob) - better_hi_prob - better_lo_prob;
      sum_our_vals += our_prob * (win_probs[k] - lose_prob) * half_pot;
      double sum_consistent_opp_probs = sum_opp_probs + a_probs[enc] -
	total_opp_card_probs[hi] - total_opp_card_probs[lo];
      sum_joint_probs += our_prob * sum_consistent_opp_probs;
    }
  }
  double wtd_sum_our_vals;
  double wtd_sum_joint_probs;
  if (sampling_) {
    wtd_sum_our_vals = sum_our_vals * (double)num_samples_;
    wtd_sum_joint_probs = sum_joint_probs * (double)num_samples_;
  } else {
    wtd_sum_our_vals = sum_our_vals * (double)BoardTree::BoardCount(max_street, msbd_);
    wtd_sum_joint_probs = sum_joint_probs * (double)BoardTree::BoardCount(max_street, msbd_);
  }
  if (action_sequence == target_action_sequence_) {
    if (b_pos_ == 0) sum_p1_outcomes_ -= wtd_sum_our_vals;
    else             sum_p1_outcomes_ += wtd_sum_our_vals;
    sum_target_weights_ += wtd_sum_joint_probs;
  }
  sum_weights_ += wtd_sum_joint_probs;
}
void Player :: Showdown ( Node * a_node , Node * b_node , shared_ptr < double [ ] > * reach_probs , const string & action_sequence ) { Card max_card1 = Game :: MaxCard ( ) + 1 ; double * a_probs = b_pos_ == 0 ? reach_probs [ 1 ] . get ( ) : reach_probs [ 0 ] . get ( ) ; double * b_probs = b_pos_ == 0 ? reach_probs [ 0 ] . get ( ) : reach_probs [ 1 ] . get ( ) ; unique_ptr < double [ ] > cum_opp_card_probs ( new double [ 52 ] ) ; unique_ptr < double [ ] > total_opp_card_probs ( new double [ 52 ] ) ; for ( Card c = 0 ; c < max_card1 ; ++ c ) { cum_opp_card_probs [ c ] = 0 ; total_opp_card_probs [ c ] = 0 ; } int max_street = Game :: MaxStreet ( ) ; int num_hole_card_pairs = Game :: NumHoleCardPairs ( max_street ) ; double sum_opp_probs = 0 ; for ( int hcp = 0 ; hcp < num_hole_card_pairs ; ++ hcp ) { const Card * cards = hands_ -> Cards ( hcp ) ; Card hi = cards [ 0 ] ; Card lo = cards [ 1 ] ; int enc = hi * max_card1 + lo ; double opp_prob = a_probs [ enc ] ; total_opp_card_probs [ hi ] += opp_prob ; total_opp_card_probs [ lo ] += opp_prob ; sum_opp_probs += opp_prob ; if ( opp_prob > 1.0 ) { fprintf ( stderr , " \n " , opp_prob , hcp ) ; exit ( -1 ) ; } } #if 0 if ( action_sequence == target_action_sequence_ && msbd_ == 11 && b_pos_ == 1 ) { for ( int i = 0 ; i < num_hole_card_pairs ; ++ i ) { const Card * cards = hands_ -> Cards ( i ) ; Card hi = cards [ 0 ] ; Card lo = cards [ 1 ] ; int enc = hi * max_card1 + lo ; OutputTwoCards ( hi , lo ) ; printf ( " \n " , reach_probs [ 1 ] [ enc ] , i ) ; fflush ( stdout ) ; } } #endif double opp_cum_prob = 0 ; unique_ptr < double [ ] > win_probs ( new double [ num_hole_card_pairs ] ) ; double half_pot = a_node -> LastBetTo ( ) ; double sum_our_vals = 0 , sum_joint_probs = 0 ; int j = 0 ; while ( j < num_hole_card_pairs ) { int last_hand_val = hands_ -> HandValue ( j ) ; int begin_range = j ; while ( j < num_hole_card_pairs ) { const Card * cards = hands_ -> Cards ( j ) ; Card hi = cards [ 0 ] ; Card lo = cards [ 1 ] ; int hand_val = hands_ -> HandValue ( j ) ; if ( hand_val != last_hand_val ) break ; win_probs [ j ] = opp_cum_prob - cum_opp_card_probs [ hi ] - cum_opp_card_probs [ lo ] ; ++ j ; } for ( int k = begin_range ; k < j ; ++ k ) { const Card * cards = hands_ -> Cards ( k ) ; Card hi = cards [ 0 ] ; Card lo = cards [ 1 ] ; int enc = hi * max_card1 + lo ; double opp_prob = a_probs [ enc ] ; if ( opp_prob <= 0 ) continue ; cum_opp_card_probs [ hi ] += opp_prob ; cum_opp_card_probs [ lo ] += opp_prob ; opp_cum_prob += opp_prob ; } for ( int k = begin_range ; k < j ; ++ k ) { const Card * cards = hands_ -> Cards ( k ) ; Card hi = cards [ 0 ] ; Card lo = cards [ 1 ] ; int enc = hi * max_card1 + lo ; double our_prob = b_probs [ enc ] ; double better_hi_prob = total_opp_card_probs [ hi ] - cum_opp_card_probs [ hi ] ; double better_lo_prob = total_opp_card_probs [ lo ] - cum_opp_card_probs [ lo ] ; double lose_prob = ( sum_opp_probs - opp_cum_prob ) - better_hi_prob - better_lo_prob ; sum_our_vals += our_prob * ( win_probs [ k ] - lose_prob ) * half_pot ; double sum_consistent_opp_probs = sum_opp_probs + a_probs [ enc ] - total_opp_card_probs [ hi ] - total_opp_card_probs [ lo ] ; sum_joint_probs += our_prob * sum_consistent_opp_probs ; } } double wtd_sum_our_vals ; double wtd_sum_joint_probs ; if ( sampling_ ) { wtd_sum_our_vals = sum_our_vals * ( double ) num_samples_ ; wtd_sum_joint_probs = sum_joint_probs * ( double ) num_samples_ ; } else { wtd_sum_our_vals = sum_our_vals * ( double ) BoardTree :: BoardCount ( max_street , msbd_ ) ; wtd_sum_joint_probs = sum_joint_probs * ( double ) BoardTree :: BoardCount ( max_street , msbd_ ) ; } if ( action_sequence == target_action_sequence_ ) { if ( b_pos_ == 0 ) sum_p1_outcomes_ -= wtd_sum_our_vals ; else sum_p1_outcomes_ += wtd_sum_our_vals ; sum_target_weights_ += wtd_sum_joint_probs ; } sum_weights_ += wtd_sum_joint_probs ; }
Compute outcome from B's perspective
Compute outcome from B ' s perspective
// fprintf(stderr, "Showdown %i\n", a_node->TerminalID()); // Make three passes through the range of equally strong hands // First pass computes win counts for each hand and finds end of range // Second pass updates cumulative counters // Third pass computes lose counts for each hand // Positions begin_range...j-1 (inclusive) all have the same hand value // This is the sum of all A reach probabilities consistent with B holding <hi, lo>. // Scale by board count