Last active
July 27, 2024 19:27
-
-
Save assyrianic/60a5be1259d811a4b1676a3999b3527a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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"); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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. | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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