Skip to content

Instantly share code, notes, and snippets.

@assyrianic
Last active July 27, 2024 19:27
Show Gist options
  • Save assyrianic/60a5be1259d811a4b1676a3999b3527a to your computer and use it in GitHub Desktop.
Save assyrianic/60a5be1259d811a4b1676a3999b3527a to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include <stdbool.h>
#include <stdlib.h>
enum CardSuit {
SUIT_HEART,
SUIT_DIAMOND,
SUIT_SPADE,
SUIT_CLUB,
MAX_SUITS,
};
enum CardFace {
ACE, TWO, THREE,
FOUR, FIVE, SIX, SEVEN,
EIGHT, NINE, TEN,
JACK, QUEEN, KING,
MAX_FACES,
};
/// Valid cards only use up 6 bits.
enum { NULL_CARD = 0xFF };
uint8_t
make_card(enum CardSuit const suit, enum CardFace const face) {
return suit | (face << 2);
}
bool
card_is_suit(uint8_t const card, enum CardSuit const suit) {
return ( card & 3 ) == suit;
}
bool
card_is_face(uint8_t const card, enum CardFace const face) {
return ( card >> 2 ) == face;
}
void
print_card(uint8_t const card) {
char const *suit_str = NULL;
switch( card & 3 ) {
case SUIT_HEART: suit_str = "heart"; break;
case SUIT_DIAMOND: suit_str = "diamond"; break;
case SUIT_SPADE: suit_str = "spade"; break;
case SUIT_CLUB: suit_str = "club"; break;
}
char const *face_str = NULL;
switch( card >> 2 ) {
case ACE: face_str = "A"; break;
case TWO: face_str = "2"; break;
case THREE: face_str = "3"; break;
case FOUR: face_str = "4"; break;
case FIVE: face_str = "5"; break;
case SIX: face_str = "6"; break;
case SEVEN: face_str = "7"; break;
case EIGHT: face_str = "8"; break;
case NINE: face_str = "9"; break;
case TEN: face_str = "10"; break;
case JACK: face_str = "J"; break;
case QUEEN: face_str = "Q"; break;
case KING: face_str = "K"; break;
}
printf("card is: %s - %s\n", suit_str, face_str);
}
void
print_cards(size_t const len, uint8_t const card[const static len]) {
for( size_t i=0; i < len; i++ ) {
print_card(card[i]);
}
}
void
init_deck(uint8_t (*const deck)[MAX_SUITS * MAX_FACES]) {
for( enum CardSuit suit = SUIT_HEART; suit < MAX_SUITS; suit++ ) {
for( enum CardFace face = ACE; face < MAX_FACES; face++ ) {
(*deck)[(suit * MAX_FACES) + face] = (suit | (face << 2));
}
}
}
void
print_deck(uint8_t const (*const deck)[MAX_SUITS * MAX_FACES]) {
for( enum CardSuit suit = SUIT_HEART; suit < MAX_SUITS; suit++ ) {
for( enum CardFace face = ACE; face < MAX_FACES; face++ ) {
print_card((*deck)[(suit * MAX_FACES) + face]);
}
}
}
struct CardDeck {
uint8_t cards[MAX_SUITS * MAX_FACES];
uint64_t removed; /// what card[s] were removed from deck.
};
struct CardDeck
card_deck_make(void) {
struct CardDeck deck;
init_deck(&deck.cards);
deck.removed = 0;
return deck;
}
void
card_deck_print(struct CardDeck const deck) {
print_deck(&deck.cards);
}
uint_fast8_t
card_deck_draw_by_index(struct CardDeck *const deck, size_t const index) {
if( index >= sizeof deck->cards ) {
return NULL_CARD;
}
size_t const bitflag = 1LU << index;
if( deck->removed & bitflag ) {
return NULL_CARD;
}
uint_fast8_t const card = deck->cards[index];
deck->removed |= bitflag;
return card;
}
uint_fast8_t
card_deck_draw_random(struct CardDeck *const deck) {
size_t index = ( size_t )(rand() % (MAX_SUITS * MAX_FACES));
uint_fast8_t card = card_deck_draw_by_index(deck, index);
if( card==NULL_CARD && deck->removed != (uint64_t)(-1LLU) ) {
while( card==NULL_CARD ) {
index = ( size_t )(rand() % (MAX_SUITS * MAX_FACES));
card = card_deck_draw_by_index(deck, index);
}
}
return card;
}
void
card_deck_draw_random_to_hands(struct CardDeck *const restrict deck, size_t const hand_len, uint8_t hand[const restrict static hand_len]) {
for( size_t i=0; i < hand_len; i++ ) {
hand[i] = card_deck_draw_random(deck);
}
}
void
sort_cards_by_face_ascending(size_t const hand_len, uint8_t hand[const static hand_len]) {
for( size_t i=0; i < hand_len; i++ ) {
for( size_t j=0; j < hand_len; j++ ) {
if( i==j ) {
continue;
} else if( (hand[i] >> 2) < (hand[j] >> 2) ) {
uint_fast8_t t = hand[i];
hand[i] = hand[j];
hand[j] = t;
}
}
}
}
void
sort_cards_by_suit_ascending(size_t const hand_len, uint8_t hand[const static hand_len]) {
for( size_t i=0; i < hand_len; i++ ) {
for( size_t j=0; j < hand_len; j++ ) {
if( i==j ) {
continue;
} else if( (hand[i] & 3) < (hand[j] & 3) ) {
uint_fast8_t t = hand[i];
hand[i] = hand[j];
hand[j] = t;
}
}
}
}
uint8_t*
combine_decks(
size_t const hand1_len,
size_t const hand2_len,
uint8_t const hand1[const restrict static hand1_len],
uint8_t const hand2[const restrict static hand2_len]
) {
uint8_t *combined_hand = calloc(hand1_len + hand2_len, sizeof *combined_hand);
for( size_t i=0; i < hand1_len; i++ ) {
combined_hand[i] = hand1[i];
}
for( size_t i=0; i < hand2_len; i++ ) {
combined_hand[hand1_len + i] = hand2[i];
}
return combined_hand;
}
bool
is_straight(
size_t const community_len,
size_t const hand_len,
uint8_t const community[const restrict static community_len],
uint8_t const hand[const restrict static hand_len],
size_t const num_cards
) {
if( num_cards > hand_len+community_len ) {
return false;
}
uint8_t *combined_hand = combine_decks(community_len, hand_len, community, hand);
size_t const combined_hand_len = community_len + hand_len;
sort_cards_by_face_ascending(combined_hand_len, combined_hand);
bool is_straight_hand = false;
for( size_t i=0; i < combined_hand_len; i++ ) {
if( is_straight_hand ) {
break;
}
size_t cascade = 0;
if( i+(num_cards-1) < combined_hand_len ) {
for( size_t n=0; n < num_cards-1; n++ ) {
cascade += (combined_hand[i+n] >> 2) == ((combined_hand[i+n+1] >> 2) - 1);
}
is_straight_hand = cascade==num_cards-1;
}
}
free(combined_hand);
return is_straight_hand;
}
bool
is_flush(
size_t const community_len,
size_t const hand_len,
uint8_t const community[const restrict static community_len],
uint8_t const hand[const restrict static hand_len],
size_t const num_cards
) {
if( num_cards > hand_len+community_len ) {
return false;
}
uint8_t *combined_hand = combine_decks(community_len, hand_len, community, hand);
size_t const combined_hand_len = community_len + hand_len;
sort_cards_by_suit_ascending(combined_hand_len, combined_hand);
bool is_flush_hand = false;
for( size_t i=0; i < combined_hand_len; i++ ) {
if( is_flush_hand ) {
break;
}
size_t cascade = 0;
if( i+(num_cards-1) < combined_hand_len ) {
for( size_t n=0; n < num_cards-1; n++ ) {
cascade += (combined_hand[i+n] & 3) == (combined_hand[i+n+1] & 3);
}
is_flush_hand = cascade==num_cards-1;
}
}
free(combined_hand);
return is_flush_hand;
}
bool
is_straight_flush(
size_t const community_len,
size_t const hand_len,
uint8_t const community[const restrict static community_len],
uint8_t const hand[const restrict static hand_len],
size_t const num_cards
) {
return is_straight(community_len, hand_len, community, hand, num_cards) && is_flush(community_len, hand_len, community, hand, num_cards);
}
bool
is_nth_of_kind(
size_t const community_len,
size_t const hand_len,
uint8_t const community[const restrict static community_len],
uint8_t const hand[const restrict static hand_len],
size_t const num_cards
) {
if( num_cards > hand_len+community_len ) {
return false;
}
uint8_t *combined_hand = combine_decks(community_len, hand_len, community, hand);
size_t const combined_hand_len = community_len + hand_len;
sort_cards_by_face_ascending(combined_hand_len, combined_hand);
bool is_nth_of_a_kind = false;
for( size_t i=0; i < combined_hand_len; i++ ) {
if( is_nth_of_a_kind ) {
break;
}
size_t cascade = 0;
if( i+(num_cards-1) < combined_hand_len ) {
for( size_t n=0; n < (num_cards-1); n++ ) {
cascade += (combined_hand[i] >> 2) == (combined_hand[i+n+1] >> 2);
}
is_nth_of_a_kind = cascade==(num_cards-1);
}
}
free(combined_hand);
return is_nth_of_a_kind;
}
int main(int const argc, char *argv[const static argc]) {
srand(time(NULL));
struct CardDeck cards = card_deck_make();
card_deck_print(cards);
puts("");
/*
enum{ HAND_SIZE = 5 };
uint8_t hand[HAND_SIZE];
card_deck_draw_random_to_hands(&cards, HAND_SIZE, hand);
print_cards(HAND_SIZE, hand);
puts("");
sort_cards_by_face_ascending(HAND_SIZE, hand);
print_cards(HAND_SIZE, hand);
*/
puts("");
bool const straight = is_straight(5, 2, (uint8_t[]){ make_card(SUIT_HEART, FOUR), make_card(SUIT_CLUB, THREE), make_card(SUIT_DIAMOND, TWO), make_card(SUIT_SPADE, FIVE), make_card(SUIT_SPADE, SIX) }, (uint8_t[]){ make_card(SUIT_HEART, KING), make_card(SUIT_CLUB, QUEEN) }, 5);
printf("is straight?: %s\n", straight? "yes" : "no");
puts("");
bool const flushed = is_flush(5, 2, (uint8_t[]){ make_card(SUIT_HEART, FOUR), make_card(SUIT_HEART, THREE), make_card(SUIT_HEART, TWO), make_card(SUIT_HEART, FIVE), make_card(SUIT_HEART, SIX) }, (uint8_t[]){ make_card(SUIT_CLUB, KING), make_card(SUIT_CLUB, QUEEN) }, 5);
printf("is flush?: %s\n", flushed? "yes" : "no");
bool const foured = is_nth_of_kind(5, 2, (uint8_t[]){ make_card(SUIT_HEART, FOUR), make_card(SUIT_CLUB, FOUR), make_card(SUIT_DIAMOND, FOUR), make_card(SUIT_HEART, FIVE), make_card(SUIT_HEART, SIX) }, (uint8_t[]){ make_card(SUIT_SPADE, FOUR), make_card(SUIT_CLUB, QUEEN) }, 4);
printf("is foured?: %s\n", foured? "yes" : "no");
}
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
enum CardSuit {
SUIT_CLUB,
SUIT_DIAMOND,
SUIT_HEART,
SUIT_SPADE,
MAX_SUITS,
};
enum CardFace {
TWO, THREE,
FOUR, FIVE, SIX, SEVEN,
EIGHT, NINE, TEN,
JACK, QUEEN, KING,
ACE,
MAX_FACES,
};
static char const *restrict cards_cstr[] = {
"🃒", "🃓", "🃔", "🃕", "🃖", "🃗", "🃘", "🃙", "🃚", "🃛", "🃝", "🃞", "🃑",
"🃂", "🃃", "🃄", "🃅", "🃆", "🃇", "🃈", "🃉", "🃊", "🃋", "🃍", "🃎", "🃁",
"🂲", "🂳", "🂴", "🂵", "🂶", "🂷", "🂸", "🂹", "🂺", "🂻", "🂽", "🂾", "🂱",
"🂢", "🂣", "🂤", "🂥", "🂦", "🂧", "🂨", "🂩", "🂪", "🂫", "🂭", "🂮", "🂡",
"🂠", "🂠", "🂠", "🂠", "🂠", "🂠", "🂠", "🂠", "🂠", "🂠", "🂠", "🂠",
};
enum {
MAX_DECK_CSTR_LEN = sizeof "🂡" * (MAX_CARDS),
MAX_CARDS = (MAX_SUITS * MAX_FACES),
};
size_t
bit_index_from_card(enum CardSuit const suit, enum CardFace const face) {
return (suit * MAX_FACES) + face;
}
void
card_from_bit_index(size_t const index, enum CardSuit *const suit, enum CardFace *const face) {
*suit = index / MAX_FACES;
*face = index % MAX_FACES;
}
uint64_t
bit_index_to_deck(size_t const idx) {
return (1ULL << idx);
}
uint64_t
card_to_deck(enum CardSuit const suit, enum CardFace const face) {
return (1ULL << bit_index_from_card(suit, face));
}
uint64_t
make_52_card_deck(void) {
return (1ULL << 52ULL) - 1;
}
bool
has_card_idx(uint64_t const hand, size_t const idx) {
return (hand & (1ULL << idx)) > 0;
}
bool
has_card(uint64_t const hand, enum CardSuit const suit, enum CardFace const face) {
return has_card_idx(hand, bit_index_from_card(suit, face));
}
uint64_t
rm_card_idx(uint64_t const hand, size_t const idx) {
return hand & ~(1ULL << idx);
}
uint64_t
rm_card(uint64_t const hand, enum CardSuit const suit, enum CardFace const face) {
return rm_card_idx(hand, bit_index_from_card(suit, face));
}
uint64_t
add_card_idx(uint64_t const hand, size_t const idx) {
return hand | (1ULL << idx);
}
uint64_t
add_card(uint64_t const hand, enum CardSuit const suit, enum CardFace const face) {
return add_card_idx(hand, bit_index_from_card(suit, face));
}
char const*
cards_to_cstr(uint64_t const hand, char cards_buff[const static MAX_DECK_CSTR_LEN + 1]) {
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
for( size_t face=0; face < MAX_FACES; face++ ) {
size_t const idx = bit_index_from_card(suit, face);
if( has_card_idx(hand, idx) ) {
strcat(cards_buff, cards_cstr[idx]);
}
}
}
return cards_buff;
}
size_t
count_face_in_hand(uint64_t const hand, enum CardFace const face) {
size_t sum = 0;
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
size_t const bit_idx = bit_index_from_card(suit, face);
if( (hand & (1ULL << bit_idx))==0 ) {
continue;
}
sum += 1;
}
return sum;
}
enum CardFace
highest_face_in_hand(uint64_t const hand) {
for( size_t face=KING; face < MAX_FACES; face-- ) {
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
size_t const bit_idx = bit_index_from_card(suit, face);
if( hand & (1ULL << bit_idx) ) {
return face;
}
}
}
return MAX_FACES;
}
bool
has_flush(uint64_t const hand, size_t const num) {
bool flush = false;
if( num > MAX_FACES ) {
return flush;
}
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
if( flush ) {
break;
}
size_t cascade = 0;
for( size_t face=0; face < MAX_FACES; face++ ) {
size_t const bit_idx = bit_index_from_card(suit, face);
if( (hand & (1ULL << bit_idx))==0 ) {
continue;
}
cascade += 1;
}
flush = cascade==num;
}
return flush;
}
bool
has_straight(uint64_t const hand, size_t const num) {
bool straight = false;
if( num > MAX_FACES ) {
return straight;
}
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
if( straight ) {
break;
}
size_t cascade = 0;
bool found_first = false;
for( size_t face=0; face < MAX_FACES; face++ ) {
size_t const bit_idx = bit_index_from_card(suit, face);
if( (hand & (1ULL << bit_idx))==0 ) {
if( !found_first ) {
continue;
} else {
break;
}
}
found_first = true;
cascade += 1;
}
straight = cascade==num;
}
return straight;
}
bool
has_straight_flush(uint64_t const hand, size_t const num) {
return has_flush(hand, num) && has_straight(hand, num);
}
bool
has_royal_flush(uint64_t const hand, size_t const num) {
bool const flushed = has_flush(hand, num);
if( !flushed ) {
return false;
}
size_t num_faces[MAX_FACES] = {0};
for( size_t face=0; face < MAX_FACES; face++ ) {
num_faces[face] = count_face_in_hand(hand, face);
}
return num_faces[ACE] && num_faces[KING] && num_faces[QUEEN] && num_faces[JACK] && num_faces[TEN];
}
bool
has_nth_of_kind(uint64_t const hand, size_t const num) {
bool nth_kind = false;
if( num > MAX_SUITS ) {
return nth_kind;
}
for( size_t face=0; face < MAX_FACES; face++ ) {
if( nth_kind ) {
break;
}
size_t cascade = 0;
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
size_t const bit_idx = bit_index_from_card(suit, face);
if( (hand & (1ULL << bit_idx))==0 ) {
continue;
}
cascade += 1;
}
nth_kind = cascade==num;
}
return nth_kind;
}
bool
has_full_house(uint64_t const hand, size_t const num) {
if( num > MAX_FACES ) {
return false;
}
size_t num_faces[MAX_FACES] = {0};
for( size_t face=0; face < MAX_FACES; face++ ) {
num_faces[face] = count_face_in_hand(hand, face);
}
/// sort descending order.
for( size_t i=0; i < MAX_FACES; i++ ) {
for( size_t j=0; j < MAX_FACES; j++ ) {
if( i==j ) {
continue;
} else if( num_faces[i] > num_faces[j] ) {
size_t t = num_faces[i];
num_faces[i] = num_faces[j];
num_faces[j] = t;
}
}
}
return (num_faces[0] + num_faces[1])==num;
}
int
main(int const argc, char *argv[const restrict static argc]) {
srand(time(NULL));
/*
printf("has_flush: %i\n", has_flush(31, 5));
printf("has_straight: %i\n", has_straight(0x1F00000, 5));
printf("has_nth_of_kind: %i\n", has_nth_of_kind(card_to_deck(SUIT_HEART, ACE) | card_to_deck(SUIT_DIAMOND, ACE) | card_to_deck(SUIT_CLUB, ACE) | card_to_deck(SUIT_SPADE, ACE), 4));
printf("has_full_house: %i\n", has_full_house(card_to_deck(SUIT_HEART, ACE) | card_to_deck(SUIT_DIAMOND, ACE) | card_to_deck(SUIT_CLUB, ACE) | card_to_deck(SUIT_SPADE, TWO) | card_to_deck(SUIT_DIAMOND, TWO) | card_to_deck(SUIT_CLUB, TWO), 6));
printf("has_royal_flush: %i\n", has_royal_flush(card_to_deck(SUIT_HEART, ACE) | card_to_deck(SUIT_HEART, KING) | card_to_deck(SUIT_HEART, QUEEN) | card_to_deck(SUIT_HEART, JACK) | card_to_deck(SUIT_HEART, NINE) | card_to_deck(SUIT_CLUB, TWO), 5));
*/
enum {
NUM_PLAYERS = 5,
START_CASH = 1000,
START_BLIND = 20,
MAIN_PLAYER = 0,
};
bool keep_playing = true;
enum GameState {
INIT = 0, /// give everybody their cards, remove blinds from players.
PLAY = 1, /// fold, bet, raise, or check if nobody raised, for each player.
DRAW3 = 2, /// get the first 3 community cards.
DRAW1_1 = 4, /// get the second-to-last community card.
DRAW1_2 = 8, /// get the last community card.
SHOWDOWN, /// determine winner, winner takes all.
};
while( keep_playing ) {
uint64_t deck = make_52_card_deck();
uint32_t player_folded[NUM_PLAYERS] = {false};
//uint32_t player_cash[NUM_PLAYERS] = {START_CASH};
uint64_t player_hands[NUM_PLAYERS] = {0};
uint64_t community = 0;
for( size_t i=0; i < NUM_PLAYERS; i++ ) {
size_t saved_index = ( size_t )(rand()) % (MAX_CARDS);
while( !has_card_idx(deck, saved_index) ) {
saved_index = ( size_t )(rand()) % (MAX_CARDS);
}
deck = rm_card_idx(deck, saved_index);
player_hands[i] = add_card_idx(player_hands[i], saved_index);
while( !has_card_idx(deck, saved_index) ) {
saved_index = ( size_t )(rand()) % (MAX_CARDS);
}
deck = rm_card_idx(deck, saved_index);
player_hands[i] = add_card_idx(player_hands[i], saved_index);
}
char hand_cstr[MAX_DECK_CSTR_LEN + 1] = {0};
printf("your hand: %s\nwould you like to fold or play?:\n", cards_to_cstr(player_hands[MAIN_PLAYER], hand_cstr));
char response[12] = {0};
scanf(" %11s", response);
#define FLUSH_STDIN() \
do { \
int c = 0; \
while((c = getchar()) != '\n' && c != EOF); \
} while(0)
FLUSH_STDIN();
if( tolower(response[0]) != 'p' ) {
printf("would you like to keep playing?:\n");
scanf(" %11s", response);
FLUSH_STDIN();
keep_playing = response[0]=='1' || tolower(response[0])=='y';
continue;
}
/// have AI determine if it should fold or not. Later...
/// Get community cards.
for( size_t i=0; i < 3; i++ ) {
size_t saved_index = ( size_t )(rand()) % MAX_CARDS;
while( !has_card_idx(deck, saved_index) ) {
saved_index = ( size_t )(rand()) % MAX_CARDS;
}
deck = rm_card_idx(deck, saved_index);
community = add_card_idx(community, saved_index);
}
/// Make bet, raise, or check.
/// Get Penultimate community card.
/// Make bet, raise, or check.
/// Get final community card.
/// Make final bet, raise, or check.
/// Showdown and determine winner.
}
}
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
enum CardSuit {
SUIT_AT,
SUIT_HASH,
SUIT_DOLLAR,
SUIT_PERCENT,
MAX_SUITS,
};
enum {
MAX_FACES = sizeof(uint16_t),
};
struct CardFace {
uint8_t val : 4;
};
size_t
bit_index_from_card(enum CardSuit const suit, struct CardFace const face) {
return (suit * MAX_FACES) + face.val;
}
void
card_from_bit_index(size_t const index, enum CardSuit *const suit, struct CardFace *const face) {
*suit = index / sizeof(uint16_t);
face->val = index % sizeof(uint16_t);
}
uint64_t
bit_index_to_deck(size_t const idx) {
return (1ULL << idx);
}
uint64_t
card_to_deck(enum CardSuit const suit, struct CardFace const face) {
return (1ULL << bit_index_from_card(suit, face));
}
uint64_t
make_hex_card_deck(void) {
return -1ULL;
}
bool
has_card_idx(uint64_t const hand, size_t const idx) {
return (hand & (1ULL << idx)) > 0;
}
bool
has_card(uint64_t const hand, enum CardSuit const suit, struct CardFace const face) {
return has_card_idx(hand, bit_index_from_card(suit, face));
}
uint64_t
rm_card_idx(uint64_t const hand, size_t const idx) {
return hand & ~(1ULL << idx);
}
uint64_t
rm_card(uint64_t const hand, enum CardSuit const suit, struct CardFace const face) {
return rm_card_idx(hand, bit_index_from_card(suit, face));
}
uint64_t
add_card_idx(uint64_t const hand, size_t const idx) {
return hand | (1ULL << idx);
}
uint64_t
add_card(uint64_t const hand, enum CardSuit const suit, struct CardFace const face) {
return add_card_idx(hand, bit_index_from_card(suit, face));
}
char const*
cards_to_cstr(uint64_t const hand, char cards_buff[const static (MAX_SUITS * MAX_FACES) + 1]) {
char const suits[] = "@#$%";
char const faces[] = "0123456789ABCDEF";
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
for( size_t face=0; face < MAX_FACES; face++ ) {
size_t const idx = bit_index_from_card(suit, (struct CardFace){face});
if( has_card_idx(hand, idx) ) {
sprintf(cards_buff, "%c%c", suits[suit], faces[face]);
}
}
}
return cards_buff;
}
size_t
count_face_in_hand(uint64_t const hand, struct CardFace const face) {
size_t sum = 0;
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
size_t const bit_idx = bit_index_from_card(suit, face);
if( (hand & (1ULL << bit_idx))==0 ) {
continue;
}
sum += 1;
}
return sum;
}
int
highest_face_in_hand(uint64_t const hand) {
for( size_t face=0xF; face < MAX_FACES; face-- ) {
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
size_t const bit_idx = bit_index_from_card(suit, (struct CardFace){face});
if( hand & (1ULL << bit_idx) ) {
return face;
}
}
}
return -1;
}
bool
has_flush(uint64_t const hand, size_t const num) {
bool flush = false;
if( num > MAX_FACES ) {
return flush;
}
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
if( flush ) {
break;
}
size_t cascade = 0;
for( size_t face=0; face < MAX_FACES; face++ ) {
size_t const bit_idx = bit_index_from_card(suit, (struct CardFace){face});
if( (hand & (1ULL << bit_idx))==0 ) {
continue;
}
cascade += 1;
}
flush = cascade==num;
}
return flush;
}
bool
has_straight(uint64_t const hand, size_t const num) {
bool straight = false;
if( num > MAX_FACES ) {
return straight;
}
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
if( straight ) {
break;
}
size_t cascade = 0;
bool found_first = false;
for( size_t face=0; face < MAX_FACES; face++ ) {
size_t const bit_idx = bit_index_from_card(suit, (struct CardFace){face});
if( (hand & (1ULL << bit_idx))==0 ) {
if( !found_first ) {
continue;
} else {
break;
}
}
found_first = true;
cascade += 1;
}
straight = cascade==num;
}
return straight;
}
bool
has_straight_flush(uint64_t const hand, size_t const num) {
return has_flush(hand, num) && has_straight(hand, num);
}
bool
has_royal_flush(uint64_t const hand, size_t const num) {
bool const flushed = has_flush(hand, num);
if( !flushed ) {
return false;
}
size_t num_faces[MAX_FACES] = {0};
for( size_t face=0; face < MAX_FACES; face++ ) {
num_faces[face] = count_face_in_hand(hand, (struct CardFace){face});
}
return num_faces[0xb] && num_faces[0xc] && num_faces[0xd] && num_faces[0xe] && num_faces[0xf];
}
bool
has_nth_of_kind(uint64_t const hand, size_t const num) {
bool nth_kind = false;
if( num > MAX_SUITS ) {
return nth_kind;
}
for( size_t face=0; face < MAX_FACES; face++ ) {
if( nth_kind ) {
break;
}
size_t cascade = 0;
for( size_t suit=0; suit < MAX_SUITS; suit++ ) {
size_t const bit_idx = bit_index_from_card(suit, (struct CardFace){face});
if( (hand & (1ULL << bit_idx))==0 ) {
continue;
}
cascade += 1;
}
nth_kind = cascade==num;
}
return nth_kind;
}
bool
has_full_house(uint64_t const hand, size_t const num) {
if( num > MAX_FACES ) {
return false;
}
size_t num_faces[MAX_FACES] = {0};
for( size_t face=0; face < MAX_FACES; face++ ) {
num_faces[face] = count_face_in_hand(hand, (struct CardFace){face});
}
/// sort descending order.
for( size_t i=0; i < MAX_FACES; i++ ) {
for( size_t j=0; j < MAX_FACES; j++ ) {
if( i==j ) {
continue;
} else if( num_faces[i] > num_faces[j] ) {
size_t t = num_faces[i];
num_faces[i] = num_faces[j];
num_faces[j] = t;
}
}
}
return (num_faces[0] + num_faces[1])==num;
}
int
main(int const argc, char *argv[const restrict static argc]) {
srand(time(NULL));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment