Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "common.h"
- #define get_bits(value, position, bits) (((value) >> (position)) & ((1 << (bits)) - 1))
- #define set_bits(value, position, bits, update) \
- ((value) ^= (get_bits(value, position, bits) ^ (update)) << (position))
- struct game_result {
- unsigned wins;
- unsigned losses;
- unsigned ties;
- };
- unsigned char * get_hand_from_input(unsigned char, unsigned char);
- struct game_result calculate_result_frequencies(const char *, const char *, const char *);
- unsigned long long calculate_mask(const char *);
- struct game_result try_hands(const char *, const char *, const char *, unsigned char, unsigned char, unsigned long long);
- unsigned char generate_card(unsigned char);
- unsigned char determine_winner(const char *, const char *, const char *);
- unsigned char * create_hand_from_cards(const char *);
- unsigned char parse_card(const char *);
- unsigned score_hand(unsigned char *, unsigned);
- unsigned get_hand_characteristic(unsigned);
- unsigned score_characteristic(unsigned);
- unsigned search_insert(unsigned, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char);
- int main (void) {
- unsigned char * hand1 = NULL;
- unsigned char * hand2 = NULL;
- unsigned char * community = NULL;
- while (!hand1) {
- printf("Enter player 1's hand (2 cards): ");
- hand1 = get_hand_from_input(2, 2);
- if (!hand1) printf("Invalid hand.\n");
- }
- while (!hand2) {
- printf("Enter player 2's hand (2 cards): ");
- hand2 = get_hand_from_input(2, 2);
- if (!hand2) printf("Invalid hand.\n");
- }
- while (!community) {
- printf("Enter up to 5 community cards: ");
- community = get_hand_from_input(0, 5);
- if (!community) printf("Invalid input.\n");
- }
- unsigned long long mask = calculate_mask(hand1) | calculate_mask(hand2) | calculate_mask(community);
- unsigned char card, count = 0;
- for (card = 0; card < 64; card ++) if (mask & (1ULL << card)) count ++;
- if ((strlen((char *) hand1) + strlen((char *) hand2) + strlen((char *) community)) != count) {
- printf("There are duplicate cards in the input.\n");
- return 1;
- }
- struct game_result odds = calculate_result_frequencies(hand1, hand2, community);
- free(hand1);
- free(hand2);
- free(community);
- double p1, p2, tie;
- unsigned total;
- total = odds.wins + odds.losses + odds.ties;
- p1 = ((double) odds.wins) * 100 / total;
- p2 = ((double) odds.losses) * 100 / total;
- tie = ((double) odds.ties) * 100 / total;
- printf("P1 win:% 11.6f%%\nP2 win:% 11.6f%%\nDraw :% 11.6f%%\n", p1, p2, tie);
- return 0;
- }
- unsigned char * get_hand_from_input (unsigned char min_cards, unsigned char max_cards) {
- char * line = get_line(NULL);
- unsigned char * hand = create_hand_from_cards(line);
- free(line);
- if (!hand) return NULL;
- if ((strlen((char *) hand) < min_cards) || (strlen((char *) hand) > max_cards)) {
- free(hand);
- return NULL;
- }
- return hand;
- }
- struct game_result calculate_result_frequencies (const char * player1, const char * player2, const char * community) {
- if (!community) community = "";
- if (strlen(player1) != 2) return (struct game_result) {.wins = 0, .losses = 0, .ties = 0};
- if (strlen(player2) != 2) return (struct game_result) {.wins = 0, .losses = 0, .ties = 0};
- if (strlen(community) > 5) return (struct game_result) {.wins = 0, .losses = 0, .ties = 0};
- if (strlen(community) == 5) {
- unsigned char result = determine_winner(player1, player2, community);
- switch (result) {
- case 0: return (struct game_result) {.wins = 0, .losses = 0, .ties = 1};
- case 1: return (struct game_result) {.wins = 1, .losses = 0, .ties = 0};
- case 2: return (struct game_result) {.wins = 0, .losses = 1, .ties = 0};
- }
- return (struct game_result) {.wins = 0, .losses = 0, .ties = 0};
- }
- unsigned long long mask = calculate_mask(player1) | calculate_mask(player2) | calculate_mask(community);
- return try_hands(player1, player2, community, strlen(community), 0, mask);
- }
- unsigned long long calculate_mask (const char * cards) {
- unsigned long long mask = 0;
- const char * card;
- for (card = cards; *card; card ++) mask |= 1ULL << *card;
- return mask;
- }
- struct game_result try_hands (const char * player1, const char * player2, const char * community,
- unsigned char position, unsigned char base, unsigned long long mask) {
- struct game_result accumulated = {.wins = 0, .losses = 0, .ties = 0};
- struct game_result next_result;
- unsigned char cards[6];
- unsigned char card, value, result;
- cards[5] = 0;
- memcpy(cards, community, position);
- for (card = base; card < (48 + position); card ++) {
- value = generate_card(card);
- if (mask & (1ULL << value)) continue;
- cards[position] = value;
- if (position == 4) {
- result = determine_winner(player1, player2, cards);
- switch (result) {
- case 0: accumulated.ties ++; break;
- case 1: accumulated.wins ++; break;
- case 2: accumulated.losses ++;
- }
- } else {
- next_result = try_hands(player1, player2, cards, position + 1, card + 1, mask);
- accumulated.wins += next_result.wins;
- accumulated.ties += next_result.ties;
- accumulated.losses += next_result.losses;
- }
- }
- return accumulated;
- }
- unsigned char generate_card (unsigned char index) {
- return ((index / 13) << 4) | ((index % 13) + 2);
- }
- unsigned char determine_winner (const char * player1, const char * player2, const char * community) {
- char p1hand[8];
- char p2hand[8];
- memcpy(p1hand, player1, 2);
- memcpy(p2hand, player2, 2);
- memcpy(p1hand + 2, community, 6);
- memcpy(p2hand + 2, community, 6);
- unsigned score1 = score_hand(p1hand, 7);
- unsigned score2 = score_hand(p2hand, 7);
- if (score1 > score2) return 1;
- if (score2 > score1) return 2;
- return 0;
- }
- unsigned char * create_hand_from_cards (const char * card_list) {
- if ((!card_list) || (!*card_list)) {
- char * empty = malloc(1);
- *empty = 0;
- return empty;
- }
- char ** card_names = tokenize_string(card_list, NULL, 1);
- unsigned char * hand = malloc(1);
- unsigned length;
- unsigned char card;
- for (length = 0; card_names[length]; length ++) {
- card = parse_card(card_names[length]);
- if (!card) {
- free(hand);
- free(card_names);
- return NULL;
- }
- hand[length] = card;
- hand = realloc(hand, length + 2);
- }
- free(card_names);
- hand[length] = 0;
- return hand;
- }
- unsigned char parse_card (const char * card) {
- if (strlen(card) != 2) return 0;
- unsigned char value;
- if ((*card >= '2') && (*card <= '9'))
- value = *card - '0';
- else
- switch (*card) {
- case 'T': case 't': value = 10; break;
- case 'J': case 'j': value = 11; break;
- case 'Q': case 'q': value = 12; break;
- case 'K': case 'k': value = 13; break;
- case 'A': case 'a': value = 14; break;
- default: return 0;
- }
- switch(card[1]) {
- case 'C': case 'c': break;
- case 'D': case 'd': value |= 0x10; break;
- case 'H': case 'h': value |= 0x20; break;
- case 'S': case 's': value |= 0x30; break;
- default: return 0;
- }
- return value;
- }
- unsigned score_hand(unsigned char * cards, unsigned count) {
- if (!count) return score_hand(cards, strlen((char *) cards));
- if (count < 5) return 0;
- if (count == 5) {
- unsigned hand = 0;
- unsigned char card_pos;
- for (card_pos = 0; card_pos < 5; card_pos ++) {
- hand <<= 6;
- hand |= cards[card_pos];
- }
- hand = get_hand_characteristic(hand);
- if (!hand) return 0;
- return score_characteristic(hand);
- }
- unsigned combination[5] = {0, 1, 2, 3, 4};
- unsigned max_score = 0;
- unsigned score;
- signed char index, ii;
- unsigned char card_values[5];
- while (1) {
- for (index = 4; index >= 0; index --) {
- combination[index] ++;
- for (ii = index + 1; ii < 5; ii ++) combination[ii] = combination[ii - 1] + 1;
- if (combination[4] < count) break;
- }
- if (index < 0) return max_score;
- for (ii = 0; ii < 5; ii ++) card_values[ii] = cards[combination[ii]];
- score = score_hand(card_values, 5);
- if (score > max_score) max_score = score;
- }
- }
- unsigned get_hand_characteristic (unsigned hand) {
- unsigned characteristic = 0;
- unsigned char lastsuit = get_bits(hand, 4, 2);
- unsigned char rank, suit, position, count;
- for (position = 0; position < 5; position ++) {
- rank = hand & 15;
- if ((rank < 2) || (rank == 15)) return 0;
- suit = get_bits(hand, 4, 2);
- hand >>= 6;
- if (lastsuit != suit) lastsuit = 4;
- count = get_bits(characteristic, 2 * rank - 4, 2);
- if (count == 3) {
- set_bits(characteristic, 2 * rank - 4, 2, 0);
- set_bits(characteristic, 28, 4, rank);
- } else
- set_bits(characteristic, 2 * rank - 4, 2, count + 1);
- }
- if (lastsuit != 4) set_bits(characteristic, 28, 4, 1);
- return characteristic;
- }
- unsigned score_characteristic (unsigned characteristic) {
- if (characteristic == 0x01000055) return 0x400005;
- if (characteristic == 0x11000055) return 0x800005;
- if (characteristic >= 0x20000000)
- return 0x700000 | (get_bits(characteristic, 28, 4) << 4) | search_insert(characteristic, 1, 1, 0, 0, 0);
- unsigned char counts = 0;
- unsigned char current, pos;
- for (pos = 0; pos < 13; pos ++) {
- current = get_bits(characteristic, 2 * pos, 2);
- if (current) counts += 1 << (3 * (current - 1));
- }
- switch (counts) {
- case 0110:
- return 0x600000 | search_insert(characteristic, 2, 1, 0, 3, 1);
- case 0102:
- return 0x300000 | search_insert(characteristic, 1, 2, 0, 3, 2);
- case 0021:
- return 0x200000 | search_insert(characteristic, 2, 2, 1, 1, 0);
- case 0013:
- return 0x100000 | search_insert(characteristic, 1, 3, 0, 2, 3);
- case 0005:
- break;
- default:
- return 0;
- }
- unsigned score = search_insert(characteristic, 1, 5, 0, 0, 0);
- if (!((score + 0x1234) % 0x11111))
- return ((get_bits(characteristic, 28, 4) == 1) ? 0x800000 : 0x400000) + ((score + 0x1234) / 0x11111);
- if (get_bits(characteristic, 28, 4) == 1) score += 0x500000;
- return score;
- }
- unsigned search_insert (unsigned characteristic, unsigned char target_count, unsigned char amount, unsigned char base,
- unsigned char special, unsigned char special_position) {
- unsigned char pos, current;
- unsigned score = 0;
- for (pos = 12; (pos < 13) && (special || amount); pos --) {
- current = get_bits(characteristic, pos * 2, 2);
- if (!current) continue;
- if (current == special) {
- set_bits(score, 4 * special_position, 4, pos + 2);
- special = 0;
- continue;
- }
- if (amount && (current == target_count)) {
- amount --;
- set_bits(score, 4 * (base + amount), 4, pos + 2);
- }
- }
- return score;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement