public Card_Info[] extract_cards(string raw_input) { Card_Info[] info_arr = new Card_Info[10]; int arr_index = 0; string[] raw_choices = raw_input.Split(new char[] { ',', ';' }); foreach (string raw_choice in raw_choices) { string[] split_raw = raw_choice.Split(new char[] { ' ' }); for (int i = 0; i < split_raw.Length; i++) { Card_Value val = text_to_value(split_raw[i]); if (val != Card_Value.END) { // found the card value of the split Card_Info card_info = new Card_Info(); card_info.value = val; card_info.suite = text_to_suite(split_raw[i + 2]); info_arr[arr_index++] = card_info; } } } return(info_arr); }
private void set_call_threshholds(ref Method_Data data, int n_folds, Card_Value high_card_value) { int bet = data.bet; Hand_Values hand_value = data.hand_value; if (bet == 0) { data.CALL_THRESHHOLD_MIN = Money.DEFAULT_ANTE - 4; data.CALL_THRESHHOLD_MAX = Money.DEFAULT_ANTE + 4; } else if (wealth_type == Wealth_Types.ALRIGHT) { data.CALL_THRESHHOLD_MIN = (double)bet * .85; data.CALL_THRESHHOLD_MAX = (double)bet * 1.15; } else if (wealth_type == Wealth_Types.WELL_OFF) { data.CALL_THRESHHOLD_MIN = (double)bet * .82; data.CALL_THRESHHOLD_MAX = (double)bet * 1.18; } else if (wealth_type == Wealth_Types.RICH) { data.CALL_THRESHHOLD_MIN = (double)bet * .73; data.CALL_THRESHHOLD_MAX = (double)bet * 1.27; } else { data.CALL_THRESHHOLD_MIN = (double)bet * .9; data.CALL_THRESHHOLD_MAX = (double)bet * 1.1; } // determines when the AI are going to call a player on bullcrap bluffs if (n_folds > 6 - (int)perception_type) { if (hand_value > Hand_Values.HIGH_CARD) { data.CALL_THRESHHOLD_MIN = (double)5; } else if (high_card_value > Card_Value.JACK) { data.CALL_THRESHHOLD_MIN = (double)25; } } }
static private void display(Card_Suite suite, Card_Value value) { string val_str = value.ToString().ToLower(); val_str = val_str.ElementAt(0).ToString().ToUpper() + val_str.Substring(1); string sui_str = suite.ToString().ToLower(); sui_str = sui_str.ElementAt(0).ToString().ToUpper() + sui_str.Substring(1); // guard conditions if (value == Card_Value.JOKER) { Console.WriteLine("{0}", val_str); } else if (suite == Card_Suite.END || value == Card_Value.END) { Console.WriteLine("Invalid card passed"); } else { Console.WriteLine("{0} of {1}", val_str, sui_str); } }
private void modify_chances(Hand_Values hand_value, Card_Value card_value) { // establish base chance off of hand value //chances = .09 * ((int)(hand_value) + 1); double[] chance_arr = new double[10]; /* double total_cards = 52 * 51 * 50 * 49 * 48; const int N_SUITES = 4; const int N_STRAIGHTS = 10; const int N_IN_SUITE = 13; const int N_CARDS = 52; const int MAX = 5; double DENOM = combination(N_CARDS, MAX); double any_suites = Math.Pow(combination(N_SUITES, 1), MAX); double royal_flush_chance = (double)N_SUITES * combination(5, MAX) / DENOM; double royal_straight_chance = (double)any_suites * combination(5, MAX) - N_SUITES * combination(5, MAX) // exclude royal flush chance / DENOM; double straight_flush_chance = (double)N_SUITES * N_STRAIGHTS * combination(5, MAX) - N_SUITES * combination(5, MAX) // exclude royal flush chance / DENOM; double four_of_a_kind_chance = (double)N_IN_SUITE * combination(4, 4) * combination((N_IN_SUITE - 1) * N_SUITES, MAX) / DENOM; double full_house_chance = (double)N_IN_SUITE * combination(4, 3) * (N_IN_SUITE - 1) * combination(4, 2) / DENOM; double flush_chance = (double)N_SUITES * combination(N_IN_SUITE, MAX) - (double)N_SUITES * N_STRAIGHTS * combination(5, MAX) // exclude straight flushes and royal flush / DENOM; double straight_chance = (double)any_suites * N_STRAIGHTS * combination(5, MAX) - (double)N_SUITES * N_STRAIGHTS * combination(5, MAX) // exclude royal straight and straight flushes / DENOM; double three_of_a_kind_chance = (double)N_IN_SUITE * combination(4, 3) * combination((int)(N_SUITES * (N_IN_SUITE - 1)), 2) - (double)N_IN_SUITE * combination(4, 4) * combination ((N_IN_SUITE - 1) * N_SUITES, MAX) // exclude four of a kind - (double)N_IN_SUITE * combination(4, 3) * (N_IN_SUITE - 1) * combination(4, 2) // exclude full house / DENOM; double two_pair_chance = (double)N_IN_SUITE * combination(4, 2) * (N_IN_SUITE - 1) * combination(4, 2) - (double)N_IN_SUITE * combination(4, 3) * (N_IN_SUITE - 1) * combination(4, 2) // exclude full house chances / DENOM; double one_pair_chance = (double)N_IN_SUITE * combination(4, 2) / DENOM - full_house_chance - three_of_a_kind_chance - two_pair_chance - full_house_chance - four_of_a_kind_chance; double remaining_chance = 0; // fill chance_arr chance_arr[0] = one_pair_chance; chance_arr[1] = two_pair_chance; chance_arr[2] = three_of_a_kind_chance; chance_arr[3] = straight_chance; chance_arr[4] = flush_chance; chance_arr[5] = full_house_chance; chance_arr[6] = four_of_a_kind_chance; chance_arr[7] = straight_flush_chance; chance_arr[8] = royal_straight_chance; chance_arr[9] = royal_flush_chance; // calculate remaining_chance for(int i = 0; i < chance_arr.Length; i++){ remaining_chance -= chance_arr[i]; if((int)hand_value == i){ break; } } // adjust remaining chances based off of card value if(hand_value == Hand_Values.HIGH_CARD){ if((int)card_value == 0){ ++card_value; } remaining_chance /= (int)card_value; } double royal_flush_chance = (double)N_SUITES * (5 * 4 * 3 * 2 * 1) / total_cards; double royal_straight_chance = (double)(Math.Pow(N_SUITES, (double)5) * (5 * 4 * 3 * 2 * 1) / total_cards; double straight_flush_chance = ((double)N_SUITES * (N_STRAIGHTS) * (5 * 4 * 3 * 2 * 1) - (N_SUITES * N_STRAIGHTS))/ total_cards; // account for royal flush chance at end double four_of_a_kind_chance = (double)N_IN_SUITE * (4 * 3 * 2 * 1 * (N_IN_SUITE - 1) * N_SUITES) / total_cards; double full_house_chance = (double)N_IN_SUITE * (52 * 3 * 2) * (double)(N_IN_SUITE - 1) * (49 * 3) / total_cards; double flush_chance = ((double)N_SUITES * (N_IN_SUITE * (N_IN_SUITE - 1) * (N_IN_SUITE - 2) * (N_IN_SUITE - 3) * (N_IN_SUITE - 4)) - (N_SUITES * N_STRAIGHTS)) / total_cards; // account for the straight flushes at the end double straight_chance = ((double)N_STRAIGHTS * Math.Pow(N_SUITES, (double)5) - N_SUITES * N_STRAIGHTS) * (5 * 4 * 3 * 2 * 1) / total_cards; // account for straight flushes (n_suites * n_straights) */ double one_pair_chance = (double)3 / 51 * 48 / 50 * 47 / 49 * 46 / 48; chance_arr[0] = one_pair_chance; double two_pair_chance = (double)6 / 50 * 5 / 49 * 44 / 48; chance_arr[1] = two_pair_chance; double three_of_a_kind_chance = (double)3 / 51 * 2 / 50 * 48 / 49 * 47 / 48; chance_arr[2] = three_of_a_kind_chance; double flush_chance = (double)12 / 51 * 11 / 50 * 10 / 49 * 9 / 48; chance_arr[3] = flush_chance; double full_house_chance = (double)6 / 50 * 5 / 49 * 4 / 48; chance_arr[4] = full_house_chance; double royal_straight_chance = (double)20 / 52 * 16 / 51 * 12 / 50 * 8 / 49 * 4 / 48; double straight_chance = royal_straight_chance * 5; chance_arr[5] = straight_chance; chance_arr[6] = royal_straight_chance; double four_of_a_kind_chance = (double)3 / 51 * 2 / 50 * 1 / 49; chance_arr[7] = four_of_a_kind_chance; double straight_flush_chance = straight_chance / 13; chance_arr[8] = straight_flush_chance; double royal_flush_chance = (double)20 / 52 * 4 / 51 * 3 / 50 * 2 / 49 * 1 / 48; chance_arr[9] = royal_flush_chance; double chance_of_better_hand = 0; if(hand_value == Hand_Values.HIGH_CARD){ for(int i = 0; i < chance_arr.Length; i++){ chance_of_better_hand += (1 - (1 - chance_arr[i]) * (1 - chance_arr[i])); } } else{ for(int i = chance_arr.Length - 1; i >= (int)hand_value; i--){ chance_of_better_hand += (1 - (1 - chance_arr[i]) * (1 - chance_arr[i])); } } // adjust chances based off of how good the deciding card value of your hand is double card_value_modifier = 0; switch(hand_value){ case(Hand_Values.HIGH_CARD): card_value_modifier = 0; break; case(Hand_Values.ONE_PAIR): card_value_modifier = (one_pair_chance - one_pair_chance / (int)Card_Value.KING * (int)card_value); break; case(Hand_Values.TWO_PAIR): card_value_modifier = (two_pair_chance - two_pair_chance / (int)Card_Value.KING * (int)card_value); break; case(Hand_Values.THREE_OF_A_KIND): card_value_modifier = (three_of_a_kind_chance - three_of_a_kind_chance / (int)Card_Value.KING * (int)card_value); break; case(Hand_Values.FLUSH): card_value_modifier = flush_chance; break; case(Hand_Values.FULL_HOUSE): card_value_modifier = (full_house_chance - full_house_chance/ (int)Card_Value.KING * (int)card_value); break; case(Hand_Values.STRAIGHT): card_value_modifier = (straight_chance - straight_chance / (int)Card_Value.KING * (int)card_value); break; case(Hand_Values.ROYAL_STRAIGHT): card_value_modifier = royal_straight_chance; break; case(Hand_Values.FOUR_OF_A_KIND): card_value_modifier = (four_of_a_kind_chance - four_of_a_kind_chance / (int)Card_Value.KING * (int)card_value); break; case(Hand_Values.ROYAL_FLUSH): card_value_modifier = royal_flush_chance; break; default: break; } // calculate and set chances if (hand_value == Hand_Values.HIGH_CARD) { chances = 1 - chance_of_better_hand; chances /= (int)Card_Value.KING; chances *= (int)card_value; return; } else{ chances = 1 - chance_of_better_hand - card_value_modifier; } // modify estimated chance of winning by everyone's tells chances *= tell_chance_modifier; // adjust chances to be less than 1 if overdid it if (chances > MAX_CHANCE) { chances = MAX_CHANCE; } }
// Methods public int calculate_bet(bool bluff, bool first_turn, bool is_call, int n_folds, int bet, int total_money, int available_funds, int personal_investment, Hand_Values hand_value, Card_Value high_card_value) { // calculate chances based off of checking other players cards/current_bets, and how much they just raised // based off of hand value and chances of winning, // bet amount is based off of personality and remaining money // every chance level based off hand value is .09 update_wealth_type(available_funds); modify_chances(hand_value, high_card_value); // fill out method data to pass around Method_Data data = new Method_Data(); data.bluff = bluff; data.first_turn = first_turn; data.is_call = is_call; data.bet = bet; data.total_money = total_money; data.available_funds = available_funds; data.personal_investment = personal_investment; data.hand_value = hand_value; set_call_threshholds(ref data, n_folds, high_card_value); // pass off to personality determiner bet_method method_choice; switch (betting_type) { case (Betting_Types.STINGY): method_choice = stingy_bet; break; case(Betting_Types.RECKLESS): method_choice = reckless_bet; break; case(Betting_Types.CALCULATED): method_choice = calculated_bet; break; case(Betting_Types.ALL_IN): method_choice = all_in_bet; break; case(Betting_Types.EXTREME): method_choice = extreme_bet; break; case(Betting_Types.RANDOM): method_choice = random_bet; break; default: // Betting_Types.END chosen return 0; } double raw_amount = (double)method_choice(data); int amount = (int)raw_amount; // account for terribly inadequate hands returning a negative value if (raw_amount <= 0) { if (first_turn && data.bet < 40 && data.bet < .1 * available_funds) { return data.bet; } else { return 0; } } // adjust for tricking opponents on the first turn if (first_turn && raw_amount > data.bet){ if (data.bet == 0) { amount = (int)raw_amount; } else if ( raw_amount > data.bet * (1 + (raw_amount - data.bet)/raw_amount) ){ amount = (int)(data.bet * (1 + (raw_amount - data.bet) / raw_amount)); } else { amount = (int)raw_amount; } if (amount < data.bet) { amount = data.bet; } // amount /= 1.34; } else if (!first_turn && hand_value >= Hand_Values.TWO_PAIR) { amount = (int)(raw_amount * (2 + rand.NextDouble() / 2));//2.16); } else if (!first_turn) { amount = (int)(raw_amount * (1 + rand.NextDouble())); // 1.34); } // round off bet to make it look good if other bets have been rounded off if (round_off(bet) == bet) { int new_amount = round_off(amount); if(!(new_amount == 0 && amount != 0)) { if (new_amount >= data.bet) { amount = new_amount; } } } return amount; }
private Player[] determine_winners() { // guard conditions if (player_queue.Count < 1) { return(new Player[0]); } Player[] winners = new Player[player_queue.Count]; int index = 0; Hand_Values best_hand_value = (Hand_Values)0; Card_Value best_card_value = (Card_Value)0; // get best hand/card combo foreach (Player player in player_queue) { if (player != null && player.hand != null && !player.folded && !player.is_out) { if (player.hand.best_hand_value > best_hand_value) { best_hand_value = player.hand.best_hand_value; if (player.hand.cards[0] != null) { best_card_value = player.hand.cards[0].value; } else { Console.WriteLine("ERROR: Null card existing in hand when determining round winner."); } } else if (player.hand.best_hand_value == best_hand_value) { if (player.hand.cards[0] != null && player.hand.cards[0].value > best_card_value) { best_card_value = player.hand.cards[0].value; } } } else if (player == null || player.hand == null) { Console.WriteLine("ERROR: Null player or hand possessed by player when determining round winner."); } } foreach (Player player in player_queue) { if (player == null || player.hand == null || player.hand.cards[0] == null) { Console.WriteLine("ERROR: Null exception when determining round winner."); } else if (!player.folded && !player.is_out && player.hand.best_hand_value == best_hand_value && player.hand.cards[0].value == best_card_value) { winners[index++] = player; } } // use tiebreaker to determine the best of the winners Hand[] hands = new Hand[index]; for (int i = 0; i < index; i++) { hands[i] = winners[i].hand; } Card_Value tie_breaking_card = Hand.tie_breaker(hands); // use tie breaking card to figure out who the winner of winners is Player[] winners_of_winners = new Player[winners.Length]; Card_Value best_tie_card_value = Hand.get_best_tie_card(winners[0].hand).value; // find the best tie card value for (int i = 0; i < winners.Length; i++) { if (winners[i] == null) { break; } else { Card best_tie_card = Hand.get_best_tie_card(winners[i].hand); if (best_tie_card.value > best_tie_card_value) { best_tie_card_value = best_tie_card.value; } } } // select the winners of the winners using the tie breaking card value index = 0; for (int i = 0; i < winners.Length; i++) { if (winners[i] == null) { break; } else if (Hand.get_best_tie_card(winners[i].hand).value == best_tie_card_value) { winners_of_winners[index++] = winners[i]; } } // condense Player[] winners_no_nulls = new Player[index]; for (int i = 0; i < index; i++) { winners_no_nulls[i] = winners_of_winners[i]; } return(winners_no_nulls); }
// Methods public int calculate_bet(bool bluff, bool first_turn, bool is_call, int n_folds, int bet, int total_money, int available_funds, int personal_investment, Hand_Values hand_value, Card_Value high_card_value) { // calculate chances based off of checking other players cards/current_bets, and how much they just raised // based off of hand value and chances of winning, // bet amount is based off of personality and remaining money // every chance level based off hand value is .09 update_wealth_type(available_funds); modify_chances(hand_value, high_card_value); // fill out method data to pass around Method_Data data = new Method_Data(); data.bluff = bluff; data.first_turn = first_turn; data.is_call = is_call; data.bet = bet; data.total_money = total_money; data.available_funds = available_funds; data.personal_investment = personal_investment; data.hand_value = hand_value; set_call_threshholds(ref data, n_folds, high_card_value); // pass off to personality determiner bet_method method_choice; switch (betting_type) { case (Betting_Types.STINGY): method_choice = stingy_bet; break; case (Betting_Types.RECKLESS): method_choice = reckless_bet; break; case (Betting_Types.CALCULATED): method_choice = calculated_bet; break; case (Betting_Types.ALL_IN): method_choice = all_in_bet; break; case (Betting_Types.EXTREME): method_choice = extreme_bet; break; case (Betting_Types.RANDOM): method_choice = random_bet; break; default: // Betting_Types.END chosen return(0); } double raw_amount = (double)method_choice(data); int amount = (int)raw_amount; // account for terribly inadequate hands returning a negative value if (raw_amount <= 0) { if (first_turn && data.bet < 40 && data.bet < .1 * available_funds) { return(data.bet); } else { return(0); } } // adjust for tricking opponents on the first turn if (first_turn && raw_amount > data.bet) { if (data.bet == 0) { amount = (int)raw_amount; } else if (raw_amount > data.bet * (1 + (raw_amount - data.bet) / raw_amount)) { amount = (int)(data.bet * (1 + (raw_amount - data.bet) / raw_amount)); } else { amount = (int)raw_amount; } if (amount < data.bet) { amount = data.bet; } // amount /= 1.34; } else if (!first_turn && hand_value >= Hand_Values.TWO_PAIR) { amount = (int)(raw_amount * (2 + rand.NextDouble() / 2));//2.16); } else if (!first_turn) { amount = (int)(raw_amount * (1 + rand.NextDouble())); // 1.34); } // round off bet to make it look good if other bets have been rounded off if (round_off(bet) == bet) { int new_amount = round_off(amount); if (!(new_amount == 0 && amount != 0)) { if (new_amount >= data.bet) { amount = new_amount; } } } return(amount); }
// Test mainframe /* public static void Main(string[] args) { uint card_id = 0; Card card = new Card("8; diamonds; what is this garbage?", card_id++); Card card2 = new Card("13; club; what IS this??", card_id++); Card card3 = new Card("what; WHAT; huh?", card_id++); card.display(); card2.display(); card3.display(); Console.Read(); } * */ public Card(Card other) { this.suite_p = other.suite_p; this.value_p = other.value_p; this.ID_p = other.ID_p; this.mark_p = other.mark_p; this.discarded_p = other.discarded_p; this.unavailable_p = other.unavailable_p; }
public Card() { suite_p = Card_Suite.END; value_p = Card_Value.END; ID_p = 0; mark_p = ""; discarded_p = false; }
private Card[] get_straight_best(Card_Value starting_value) { Card[] best = new Card[5]; for(int i = 0; i < n_held; i++){ if(cards_p[i].value >= starting_value && cards_p[i].value < (Card_Value)((int)starting_value + 5)){ best[4 - (int)cards_p[i].value + (int)starting_value] = cards_p[i]; } } return best; }
private void fill_best(bool straight, bool flush, Card_Value straight_starting_value, Card_Suite flush_suite) { if(straight && flush){ if(best_hand_value_p == Hand_Values.ROYAL_FLUSH){ the_best_p = get_royal_straight_best(); } else{ the_best_p = get_straight_flush_best(straight_starting_value); } } else if(straight){ if(best_hand_value_p == Hand_Values.ROYAL_STRAIGHT){ the_best_p = get_royal_straight_best(); } else{ the_best_p = get_straight_best(straight_starting_value); } } else if(flush){ the_best_p = get_flush_best(flush_suite); } else{ organize_by_value(); the_best_p = get_multi_card_best(best_hand_value_p); } }
private bool check_for_straight_flush(Card_Value starting_value, Card_Suite[] flush_suites) { if(check_for_royal_flush(flush_suites)){ return true; } if(starting_value > (Card_Value)((int)Card_Value.END - 5)){ return false; } return get_straight_flush_suite(starting_value, flush_suites) != Card_Suite.END; }
// assumed to be organized by value private bool check_for_straight(out Card_Value starting_value) { organize_by_value(); const int STRAIGHT_LENGTH = 5; starting_value = Card_Value.END; if(n_held < STRAIGHT_LENGTH){ return false; } Card_Value current_card_value = Card_Value.END; int n_in_a_row = 1; bool potential_royal_flush = false; // handle royal flush cases for(int i = 1; i < n_held; i++){ current_card_value = cards_p[i].value; Card_Value previous_card_value = cards_p[i - 1].value; if(current_card_value == previous_card_value){ continue; } else if(current_card_value == previous_card_value - 1){ ++n_in_a_row; starting_value = current_card_value; if(starting_value == Card_Value.TEN && n_in_a_row >= STRAIGHT_LENGTH - 1){ potential_royal_flush = true; } } else if(current_card_value == Card_Value.ACE){ if(potential_royal_flush){ starting_value = Card_Value.TEN; return true; } } else{ n_in_a_row = 1; starting_value = current_card_value; } } if(n_in_a_row >= STRAIGHT_LENGTH){ return true; } else{ return false; } }
// Methods // bet // ante_up // end_turn // fold // pay_big_blind // pay_small_blind // pay_up // raise // should skip // status_refresh private int calculate_bet(bool first_turn, bool is_call, int call_amount, int actions_so_far_this_turn) { if (hand.cards.Length < 1 || hand.cards[0] == null) { return(0); } Hand_Values hand_value = hand.best_hand_value; int personal_investment = money.current_bet; Card_Value high_card_value = hand.cards[0].value; int amount = personality.calculate_bet( bluff, // determines whether AI will bluff first_turn, // whether a round of discards/betting has occurred is_call, // whether someone has already bet n_folds, // # of rounds ending in a fold -> pushes AI to bet or call bluffs call_amount, // the current amount AI will have to match to stay in money.current_amount, // money in possession (including what's been bet) available_funds, // money allowed to bet personal_investment, // money already placed up for bet hand_value, // value of the hand high_card_value); // determining card value of the hand // prevent from looping // also another factor determining if you should call instead of raise const double PERCENTAGE_GATE = .13; double loop_flag_percentage = 0; if (personal_investment == 0 || call_amount == 0) { loop_flag_percentage = PERCENTAGE_GATE + 1; // 100 call_amount, 5000 starting funds; 2% flag_percentage } else { loop_flag_percentage = (double)call_amount / personal_investment; // 100 call_amount / 300 personal_investment = 30% } // determine if raise instead of call if (amount > call_amount) { if (loop_flag_percentage < PERCENTAGE_GATE) { // if raise, and in danger of having looped, just call instead of raise amount = call_amount; } else if (actions_so_far_this_turn > 1 && first_turn) { amount = call_amount; } else if (actions_so_far_this_turn > 4 && !first_turn) { amount = call_amount; } } // ERROR TESTING if (amount > 0 && amount < 5) { amount = 5; } return(amount); }
private void modify_chances(Hand_Values hand_value, Card_Value card_value) { // establish base chance off of hand value //chances = .09 * ((int)(hand_value) + 1); double[] chance_arr = new double[10]; /* * double total_cards = 52 * 51 * 50 * 49 * 48; * const int N_SUITES = 4; * const int N_STRAIGHTS = 10; * const int N_IN_SUITE = 13; * const int N_CARDS = 52; * const int MAX = 5; * double DENOM = combination(N_CARDS, MAX); * double any_suites = Math.Pow(combination(N_SUITES, 1), MAX); * * double royal_flush_chance = (double)N_SUITES * combination(5, MAX) / DENOM; * double royal_straight_chance = (double)any_suites * combination(5, MAX) * - N_SUITES * combination(5, MAX) // exclude royal flush chance * / DENOM; * double straight_flush_chance = (double)N_SUITES * N_STRAIGHTS * combination(5, MAX) * - N_SUITES * combination(5, MAX) // exclude royal flush chance * / DENOM; * double four_of_a_kind_chance = (double)N_IN_SUITE * combination(4, 4) * combination((N_IN_SUITE - 1) * N_SUITES, MAX) / DENOM; * double full_house_chance = (double)N_IN_SUITE * combination(4, 3) * (N_IN_SUITE - 1) * combination(4, 2) / DENOM; * double flush_chance = (double)N_SUITES * combination(N_IN_SUITE, MAX) * - (double)N_SUITES * N_STRAIGHTS * combination(5, MAX) // exclude straight flushes and royal flush * / DENOM; * double straight_chance = (double)any_suites * N_STRAIGHTS * combination(5, MAX) * - (double)N_SUITES * N_STRAIGHTS * combination(5, MAX) // exclude royal straight and straight flushes * / DENOM; * double three_of_a_kind_chance = (double)N_IN_SUITE * combination(4, 3) * combination((int)(N_SUITES * (N_IN_SUITE - 1)), 2) * - (double)N_IN_SUITE * combination(4, 4) * combination ((N_IN_SUITE - 1) * N_SUITES, MAX) // exclude four of a kind * - (double)N_IN_SUITE * combination(4, 3) * (N_IN_SUITE - 1) * combination(4, 2) // exclude full house * / DENOM; * double two_pair_chance = (double)N_IN_SUITE * combination(4, 2) * (N_IN_SUITE - 1) * combination(4, 2) * - (double)N_IN_SUITE * combination(4, 3) * (N_IN_SUITE - 1) * combination(4, 2) // exclude full house chances * / DENOM; * double one_pair_chance = (double)N_IN_SUITE * combination(4, 2) / DENOM * - full_house_chance - three_of_a_kind_chance - two_pair_chance - full_house_chance - four_of_a_kind_chance; * double remaining_chance = 0; * * // fill chance_arr * chance_arr[0] = one_pair_chance; * chance_arr[1] = two_pair_chance; * chance_arr[2] = three_of_a_kind_chance; * chance_arr[3] = straight_chance; * chance_arr[4] = flush_chance; * chance_arr[5] = full_house_chance; * chance_arr[6] = four_of_a_kind_chance; * chance_arr[7] = straight_flush_chance; * chance_arr[8] = royal_straight_chance; * chance_arr[9] = royal_flush_chance; * * // calculate remaining_chance * for(int i = 0; i < chance_arr.Length; i++){ * remaining_chance -= chance_arr[i]; * if((int)hand_value == i){ * break; * } * } * * // adjust remaining chances based off of card value * if(hand_value == Hand_Values.HIGH_CARD){ * if((int)card_value == 0){ ++card_value; * } * remaining_chance /= (int)card_value; * } * * * double royal_flush_chance = (double)N_SUITES * (5 * 4 * 3 * 2 * 1) / total_cards; * double royal_straight_chance = (double)(Math.Pow(N_SUITES, (double)5) * (5 * 4 * 3 * 2 * 1) / total_cards; * double straight_flush_chance = ((double)N_SUITES * (N_STRAIGHTS) * (5 * 4 * 3 * 2 * 1) - (N_SUITES * N_STRAIGHTS))/ total_cards; // account for royal flush chance at end * double four_of_a_kind_chance = (double)N_IN_SUITE * (4 * 3 * 2 * 1 * (N_IN_SUITE - 1) * N_SUITES) / total_cards; * double full_house_chance = (double)N_IN_SUITE * (52 * 3 * 2) * (double)(N_IN_SUITE - 1) * (49 * 3) / total_cards; * double flush_chance = ((double)N_SUITES * (N_IN_SUITE * (N_IN_SUITE - 1) * (N_IN_SUITE - 2) * (N_IN_SUITE - 3) * (N_IN_SUITE - 4)) - (N_SUITES * N_STRAIGHTS)) / total_cards; // account for the straight flushes at the end * double straight_chance = ((double)N_STRAIGHTS * Math.Pow(N_SUITES, (double)5) - N_SUITES * N_STRAIGHTS) * (5 * 4 * 3 * 2 * 1) / total_cards; // account for straight flushes (n_suites * n_straights) */ double one_pair_chance = (double)3 / 51 * 48 / 50 * 47 / 49 * 46 / 48; chance_arr[0] = one_pair_chance; double two_pair_chance = (double)6 / 50 * 5 / 49 * 44 / 48; chance_arr[1] = two_pair_chance; double three_of_a_kind_chance = (double)3 / 51 * 2 / 50 * 48 / 49 * 47 / 48; chance_arr[2] = three_of_a_kind_chance; double flush_chance = (double)12 / 51 * 11 / 50 * 10 / 49 * 9 / 48; chance_arr[3] = flush_chance; double full_house_chance = (double)6 / 50 * 5 / 49 * 4 / 48; chance_arr[4] = full_house_chance; double royal_straight_chance = (double)20 / 52 * 16 / 51 * 12 / 50 * 8 / 49 * 4 / 48; double straight_chance = royal_straight_chance * 5; chance_arr[5] = straight_chance; chance_arr[6] = royal_straight_chance; double four_of_a_kind_chance = (double)3 / 51 * 2 / 50 * 1 / 49; chance_arr[7] = four_of_a_kind_chance; double straight_flush_chance = straight_chance / 13; chance_arr[8] = straight_flush_chance; double royal_flush_chance = (double)20 / 52 * 4 / 51 * 3 / 50 * 2 / 49 * 1 / 48; chance_arr[9] = royal_flush_chance; double chance_of_better_hand = 0; if (hand_value == Hand_Values.HIGH_CARD) { for (int i = 0; i < chance_arr.Length; i++) { chance_of_better_hand += (1 - (1 - chance_arr[i]) * (1 - chance_arr[i])); } } else { for (int i = chance_arr.Length - 1; i >= (int)hand_value; i--) { chance_of_better_hand += (1 - (1 - chance_arr[i]) * (1 - chance_arr[i])); } } // adjust chances based off of how good the deciding card value of your hand is double card_value_modifier = 0; switch (hand_value) { case (Hand_Values.HIGH_CARD): card_value_modifier = 0; break; case (Hand_Values.ONE_PAIR): card_value_modifier = (one_pair_chance - one_pair_chance / (int)Card_Value.KING * (int)card_value); break; case (Hand_Values.TWO_PAIR): card_value_modifier = (two_pair_chance - two_pair_chance / (int)Card_Value.KING * (int)card_value); break; case (Hand_Values.THREE_OF_A_KIND): card_value_modifier = (three_of_a_kind_chance - three_of_a_kind_chance / (int)Card_Value.KING * (int)card_value); break; case (Hand_Values.FLUSH): card_value_modifier = flush_chance; break; case (Hand_Values.FULL_HOUSE): card_value_modifier = (full_house_chance - full_house_chance / (int)Card_Value.KING * (int)card_value); break; case (Hand_Values.STRAIGHT): card_value_modifier = (straight_chance - straight_chance / (int)Card_Value.KING * (int)card_value); break; case (Hand_Values.ROYAL_STRAIGHT): card_value_modifier = royal_straight_chance; break; case (Hand_Values.FOUR_OF_A_KIND): card_value_modifier = (four_of_a_kind_chance - four_of_a_kind_chance / (int)Card_Value.KING * (int)card_value); break; case (Hand_Values.ROYAL_FLUSH): card_value_modifier = royal_flush_chance; break; default: break; } // calculate and set chances if (hand_value == Hand_Values.HIGH_CARD) { chances = 1 - chance_of_better_hand; chances /= (int)Card_Value.KING; chances *= (int)card_value; return; } else { chances = 1 - chance_of_better_hand - card_value_modifier; } // modify estimated chance of winning by everyone's tells chances *= tell_chance_modifier; // adjust chances to be less than 1 if overdid it if (chances > MAX_CHANCE) { chances = MAX_CHANCE; } }
public Card(string card_info, uint ID) { Card_Info info = interpret(card_info); suite_p = info.suite; value_p = info.value; ID_p = ID; mark_p = info.mark; discarded_p = false; }
// assumes that only 5 cards are held private Card[] get_straight_flush_best(Card_Value starting_value) { Card[] best = get_straight_best(starting_value); int[] n_of_suite = new int[5]; for(int i = 0; i < n_held; i++){ n_of_suite[(int)cards_p[i].suite]++; } Card_Suite most_suite = (Card_Suite)0; int highest_n_of_suite = 0; for(int i = 0; i < n_of_suite.Length; i++){ if(n_of_suite[i] >= 5){ return best; } else if(n_of_suite[i] > highest_n_of_suite){ highest_n_of_suite = n_of_suite[i]; most_suite = (Card_Suite)i; } } // replace incorrect cards for(int i = 0; i < n_held; i++){ if(best[i].suite != most_suite){ for(int j = 0; j < n_held; j++){ if(cards_p[j].suite == most_suite && cards_p[j].value == best[i].value){ best[i] = cards_p[j]; } } } } return best; }
private static void display(Card_Suite suite, Card_Value value) { string val_str = value.ToString().ToLower(); val_str = val_str.ElementAt(0).ToString().ToUpper() + val_str.Substring(1); string sui_str = suite.ToString().ToLower(); sui_str = sui_str.ElementAt(0).ToString().ToUpper() + sui_str.Substring(1); // guard conditions if (value == Card_Value.JOKER) { Console.WriteLine("{0}", val_str); } else if (suite == Card_Suite.END || value == Card_Value.END) { Console.WriteLine("Invalid card passed"); } else { Console.WriteLine("{0} of {1}", val_str, sui_str); } }
private Card_Suite get_straight_flush_suite(Card_Value starting_value, Card_Suite[] flush_suites) { Card_Suite royal_flush_suite = get_royal_flush_suite(flush_suites); if(royal_flush_suite != Card_Suite.END){ return royal_flush_suite; } int[] n_in_suite = new int[flush_suites.Length]; for(int i = 0; i < n_held; i++){ Card current_card = cards_p[i]; if(current_card.value < (Card_Value)((int)starting_value + 5) && current_card.value >= starting_value){ // if it's the right value for(int suite_index = 0; suite_index < flush_suites.Length; suite_index++){ if(current_card.suite == flush_suites[suite_index]){ n_in_suite[suite_index]++; if(n_in_suite[suite_index] >= STRAIGHT_LENGTH){ return flush_suites[suite_index]; } } } } } return Card_Suite.END; }
public Card(Card_Info info, uint ID) { suite_p = info.suite; value_p = info.value; ID_p = ID; mark_p = info.mark; discarded_p = false; }
public Hand_Values calculate_best_hand_value(out Card_Value straight_starting_value, out Card_Suite flush_suite) { // have to make sure that the best hand value is updated // need to make sure the best part of the hand (the pair, two pairs, etc.) are at the front // have to distinguish between hand values straight_starting_value = Card_Value.END; flush_suite = Card_Suite.END; // initialize hand value tracking array bool[] is_hand_value = new bool[(int)Hand_Values.END]; for(int i = 0; i < is_hand_value.Length; i++){ is_hand_value[i] = false; } // check for the possibility of a flush Card_Suite[] flush_suites = check_for_flushes(); is_hand_value[(int)Hand_Values.FLUSH] = flush_suites.Length > 0; // record if it's possible for a flush if(flush_suites.Length > 0){ flush_suite = flush_suites[0]; } // check for a normal straight is_hand_value[(int)Hand_Values.STRAIGHT] = check_for_straight(out straight_starting_value); // verify this will appropriately return TEN if royal straight present // check for a normal straight flush if(is_hand_value[(int)Hand_Values.FLUSH] && is_hand_value[(int)Hand_Values.STRAIGHT]){ is_hand_value[(int)Hand_Values.STRAIGHT_FLUSH] = check_for_straight_flush(straight_starting_value, flush_suites); flush_suite = get_straight_flush_suite(straight_starting_value, flush_suites); } else{ is_hand_value[(int)Hand_Values.STRAIGHT_FLUSH] = false; } // check for royal_straights/flushes if(is_hand_value[(int)Hand_Values.STRAIGHT]){ is_hand_value[(int)Hand_Values.ROYAL_STRAIGHT] = check_for_royal_straight(); if(is_hand_value[(int)Hand_Values.ROYAL_STRAIGHT] && is_hand_value[(int)Hand_Values.FLUSH]){ is_hand_value[(int)Hand_Values.ROYAL_FLUSH] = check_for_royal_flush(flush_suites); flush_suite = get_royal_flush_suite(flush_suites); } else{ is_hand_value[(int)Hand_Values.ROYAL_FLUSH] = false; } } // check for other non-flush things // check for multi-card things Hand_Values multi_card_hand_value = check_for_multi_card_hands(); switch(multi_card_hand_value){ case(Hand_Values.FULL_HOUSE): is_hand_value[(int)Hand_Values.FULL_HOUSE] = true; is_hand_value[(int)Hand_Values.THREE_OF_A_KIND] = true; is_hand_value[(int)Hand_Values.TWO_PAIR] = true; is_hand_value[(int)Hand_Values.ONE_PAIR] = true; is_hand_value[(int)Hand_Values.HIGH_CARD] = true; break; case(Hand_Values.TWO_PAIR): is_hand_value[(int)Hand_Values.TWO_PAIR] = true; is_hand_value[(int)Hand_Values.ONE_PAIR] = true; is_hand_value[(int)Hand_Values.HIGH_CARD] = true; break; case(Hand_Values.FOUR_OF_A_KIND): is_hand_value[(int)Hand_Values.FOUR_OF_A_KIND] = true; is_hand_value[(int)Hand_Values.THREE_OF_A_KIND] = true; is_hand_value[(int)Hand_Values.ONE_PAIR] = true; is_hand_value[(int)Hand_Values.HIGH_CARD] = true; break; case(Hand_Values.THREE_OF_A_KIND): is_hand_value[(int)Hand_Values.THREE_OF_A_KIND] = true; is_hand_value[(int)Hand_Values.ONE_PAIR] = true; is_hand_value[(int)Hand_Values.HIGH_CARD] = true; break; case(Hand_Values.ONE_PAIR): is_hand_value[(int)Hand_Values.ONE_PAIR] = true; is_hand_value[(int)Hand_Values.HIGH_CARD] = true; break; case(Hand_Values.HIGH_CARD): is_hand_value[(int)Hand_Values.HIGH_CARD] = true; break; } // find the best hand value for(int i = is_hand_value.Length - 1; i >= 0; i--){ if(is_hand_value[i]){ return (Hand_Values)i; } } return Hand_Values.HIGH_CARD; }