new protected string decide_tell() { string tell_candidate = ""; if (bluff && hand.best_hand_value < Hand_Values.END) { Hand_Values bluff_hand_value = (Hand_Values)(rand.Next((int)Hand_Values.END - (int)hand.best_hand_value - 1) + (int)hand.best_hand_value) + 1; tell_candidate = base.decide_tell(bluff_hand_value); } else { tell_candidate = base.decide_tell(); } return(tell_candidate); }
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; } } }
protected string decide_tell(Hand_Values best_hand_value) { string[] tell_arr = get_tell_array(tell_type); int tier = 0; if (best_hand_value > Hand_Values.FULL_HOUSE) { tier = 3; } else if (best_hand_value > Hand_Values.ONE_PAIR) { tier = 2; } else if (best_hand_value > Hand_Values.HIGH_CARD) { tier = 1; } return(tell_arr[tier]); }
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; }
protected string decide_tell(Hand_Values best_hand_value) { string[] tell_arr = get_tell_array(tell_type); int tier = 0; if (best_hand_value > Hand_Values.FULL_HOUSE) { tier = 3; } else if (best_hand_value > Hand_Values.ONE_PAIR) { tier = 2; } else if (best_hand_value > Hand_Values.HIGH_CARD) { tier = 1; } return tell_arr[tier]; }
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); }
public Hand(Card[] cards, Deck deck, int max_size) { cards_p = cards; max_size_p = max_size; n_held_p = 0; for (int i = 0; i < cards.Length; i++) { if (cards_p[i] == null) { break; } else { ++n_held_p; } } deck_p = deck; the_best_p = new Card[max_size_p]; the_rest_p = new Card[0]; best_hand_value_p = Hand_Values.END; organize(); }
private Card[] get_multi_card_best(Hand_Values hand_value) { Card_Value val1 = cards_p[0].value; int n_val_1 = 1; Card_Value val2 = (Card_Value)0; int n_val_2 = 0; // full house // two pair // four of a kind // three of a kind // one pair // high card for(int i = 1; i < n_held; i++){ Card_Value current_val = cards_p[i].value; Card_Value previous_val = cards_p[i - 1].value; if(n_val_2 == 0){ val2 = current_val; n_val_2 = 1; } else if(current_val == previous_val){ if(current_val == val1){ ++n_val_1; } else if(current_val == val2){ ++n_val_2; } else{ if(n_val_1 < 2){ val1 = current_val; n_val_1 = 2; } else if(n_val_2 < 2){ val2 = current_val; n_val_2 = 2; } } } } Card[] best = null; Card_Value primary_val = val1; Card_Value secondary_val = val2; if(n_val_2 > n_val_1){ secondary_val = val1; primary_val = val2; } else if (n_val_1 == n_val_2 && secondary_val > primary_val) { secondary_val = val1; primary_val = val2; } int primary_index; int secondary_index; switch(hand_value){ case(Hand_Values.FULL_HOUSE): const int FULL_HOUSE_LENGTH = 5; best = new Card[FULL_HOUSE_LENGTH]; primary_index = 0; secondary_index = 3; for(int i = 0; i < n_held; i++){ if(cards_p[i].value == primary_val){ best[primary_index++] = cards_p[i]; } else if(cards_p[i].value == secondary_val){ best[secondary_index++] = cards_p[i]; } } break; case(Hand_Values.TWO_PAIR): const int TWO_PAIR_LENGTH = 4; best = new Card[TWO_PAIR_LENGTH]; primary_index = 0; secondary_index = 2; for(int i = 0; i < n_held; i++){ if(cards_p[i].value == primary_val){ best[primary_index++] = cards_p[i]; } else if(cards_p[i].value == secondary_val){ best[secondary_index++] = cards_p[i]; } } break; case(Hand_Values.FOUR_OF_A_KIND): best = new Card[4]; primary_index = 0; for(int i = 0; i < n_held; i++){ if(cards_p[i].value == primary_val){ best[primary_index++] = cards_p[i]; } } break; case(Hand_Values.THREE_OF_A_KIND): best = new Card[3]; primary_index = 0; for(int i = 0; i < n_held; i++){ if(cards_p[i].value == primary_val){ best[primary_index++] = cards_p[i]; } } break; case(Hand_Values.ONE_PAIR): best = new Card[2]; primary_index = 0; for(int i = 0; i < n_held; i++){ if(cards_p[i].value == primary_val){ best[primary_index++] = cards_p[i]; } } break; case(Hand_Values.HIGH_CARD): best = new Card[1]; Card_Value high_card_val = (Card_Value)0; for(int i = 0; i < n_held; i++){ if(cards_p[i].value > high_card_val){ high_card_val = cards_p[i].value; best[0] = cards_p[i]; } } break; } return best; }
// Constructors public Hand(Hand other) { this.cards_p = other.cards; this.max_size_p = other.max_size; this.n_held_p = other.n_held; this.deck_p = other.deck; this.the_best_p = other.the_best; this.the_rest_p = other.the_rest; this.best_hand_value_p = other.best_hand_value; }
public void organize() { Card_Value straight_starting_value; Card_Suite flush_suite; best_hand_value_p = calculate_best_hand_value(out straight_starting_value, out flush_suite); bool straight = false; bool flush = false; switch(best_hand_value){ case(Hand_Values.ROYAL_FLUSH): case(Hand_Values.STRAIGHT_FLUSH): flush = true; straight = true; break; case(Hand_Values.FLUSH): flush = true; break; case(Hand_Values.ROYAL_STRAIGHT): case(Hand_Values.STRAIGHT): straight = true; break; default: break; } fill_best(straight, flush, straight_starting_value, flush_suite); fill_rest(); organize_hand(); }
// 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; } }
private int calculated_bet(Method_Data data) { // convert data items to normal item bool bluff = data.bluff; bool first_turn = data.first_turn; bool is_call = data.is_call; int bet = data.bet; int total_money = data.total_money; int available_funds = data.available_funds; int personal_investment = data.personal_investment; double CALL_THRESHHOLD_MIN = data.CALL_THRESHHOLD_MIN; double CALL_THRESHHOLD_MAX = data.CALL_THRESHHOLD_MAX; Hand_Values hand_value = data.hand_value; double amount; // return value in double form double investment = (double)personal_investment / total_money * 8; // 0 to 1 double potential_loss = (double)bet / total_money * 4; // 0 to 1 if (potential_loss == 0) { potential_loss = (double)personal_investment / total_money * 4; } // calculate wealth_factor double money_tier = 0; if (wealth_type == Wealth_Types.POOR) { money_tier = (int)Wealth_Values.POOR; money_tier *= 1.6; } else if (wealth_type == Wealth_Types.ALRIGHT) { money_tier = (int)Wealth_Values.ALRIGHT; money_tier /= 5; } else if (wealth_type == Wealth_Types.WELL_OFF) { money_tier = (int)Wealth_Values.WELL_OFF; money_tier /= 15; } else if (wealth_type == Wealth_Types.RICH) { money_tier = (int)Wealth_Values.RICH; money_tier /= 50; } int capper = 1; int bet_temp = bet; while (bet_temp > 0) { bet_temp /= 10; ++capper; } capper *= 3; double wealth_factor = 1.8 / (((int)wealth_type + 5) / (double)2 / ((int)wealth_type + 1)); //double max_amount = potential_loss * chances * money_tier * investment * wealth_factor; // $ willing to bet double max_amount = .482 * Math.Sqrt(3 * (double)bet) + (0.0184 * (chances - 0.70) / .35) * money_tier + 5; // ERROR TESTING adjust bit in front of chances once chances gets fixed //max_amount /= capper; int[] hand_value_factors = { 1, 3, 6, 8, 9, 10, 11, 13, 15, 17, 20, 24, 30 }; /* * Console.WriteLine("Stats:"); * Console.WriteLine("\tfirst_turn: {0}", first_turn); * Console.WriteLine("\tis_call: {0}", is_call); * Console.WriteLine("\tbet: {0}", bet); * Console.WriteLine("\ttotal_money: {0}", total_money); * Console.WriteLine("\tavailable_funds: {0}", available_funds); * Console.WriteLine("\t\tpotential_loss: {0}", potential_loss); * Console.WriteLine("\t\tchances: {0}", chances); * Console.WriteLine("\t\tmoney_tier: {0}", money_tier); * Console.WriteLine("\t\tinvestment: {0}", investment); * Console.WriteLine("\t\twealth_factor: {0}", wealth_factor); * Console.WriteLine(); * Console.WriteLine("max_amount: {0}", max_amount); */ //double max_amount = 1 / potential_loss / 10 * available_funds; // anywhere from 1/250 to 1/4 // max raising of x10 // max raising first turn of x3 double adjusted_max = max_amount; if (bluff && hand_value == Hand_Values.HIGH_CARD) { adjusted_max *= hand_value_factors[rand.Next((int)Hand_Values.ROYAL_FLUSH - (int)Hand_Values.TWO_PAIR) + (int)Hand_Values.TWO_PAIR] / 3 + 1; } else { adjusted_max *= hand_value_factors[(int)hand_value] / 3 + 1; } // willingness to raise instead of call if (adjusted_max > bet && adjusted_max >= 1.6 * CALL_THRESHHOLD_MAX) { CALL_THRESHHOLD_MAX *= 2; } // Console.WriteLine(adjusted_max); if (bet < 0 || adjusted_max < 0) { amount = 0; } else if (is_call) { if (adjusted_max >= CALL_THRESHHOLD_MIN && adjusted_max <= CALL_THRESHHOLD_MAX) { amount = bet; } else if (adjusted_max > CALL_THRESHHOLD_MAX) { amount = adjusted_max; } else { amount = 0; } } else { double random_factor = rand.NextDouble() * rand.NextDouble() * (rand.Next(8) + 1) % 1; while (random_factor < .85) { random_factor *= rand.Next(3) + 2; if (random_factor > 1) { random_factor = 1; } } double recklessness_factor = ((int)wealth_type + 5) / (double)7; // Console.WriteLine("random_factor: {0}\nrecklessness: {1}", random_factor, recklessness_factor); amount = adjusted_max * random_factor * recklessness_factor; // Console.WriteLine("adjusted amount: {0}", amount); double investment_factor = 1; if (personal_investment > .9 * total_money) { investment_factor = 2000; } else if (personal_investment > .7 * total_money) { investment_factor = 3.5; } else if (personal_investment > .6 * total_money) { investment_factor = 2.5; } else if (personal_investment > .5 * total_money) { investment_factor = 2; } else { investment_factor = 1.1; investment_factor += ((double)personal_investment / total_money); } // Console.WriteLine("investment_factor: {0}", investment_factor); amount *= investment_factor; } if (amount < bet && amount != 0) { Console.WriteLine("final amount: {0}", amount); } return((int)amount); }
// 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); }