#include "server_game_process.h" #include #include #include enum { deck_size = 52 }; static const char *basic_deck[deck_size] = { "2^", "3^", "4^", "5^", "6^", "7^", "8^", "9^", "10^", "J^", "Q^", "K^", "A^", "2#", "3#", "4#", "5#", "6#", "7#", "8#", "9#", "10#", "J#", "Q#", "K#", "A#", "2%", "3%", "4%", "5%", "6%", "7%", "8%", "9%", "10%", "j%", "Q%", "K%", "A%", "2v", "3v", "4v", "5v", "6v", "7v", "8v", "9v", "10v", "Jv", "Qv", "Kv", "Av" }; static int get_random_idx() { return 0 + (int)((double)deck_size*rand()/(RAND_MAX + 1.0)); } const char** get_shuffled_deck() { int i, new_idx; const char **shuffled_deck = calloc(deck_size, sizeof(char*)); for(i = 0; i < deck_size; ++i) { new_idx = get_random_idx(); while(shuffled_deck[new_idx]) new_idx = get_random_idx(); shuffled_deck[new_idx] = basic_deck[i]; } return shuffled_deck; } void deal_first_cards(const char **shuffled_deck, int *cards_left, player_cards *deck) { int i, last_idx; const char *str; for(i = 0; i < start_deck_size; ++i) { last_idx = *cards_left-1; str = shuffled_deck[last_idx]; if(str) { push_stack(deck, str); --*cards_left; shuffled_deck[last_idx] = NULL; } } } void deal_cards(const char **shuffled_deck, int *shuffled_cards_left, struct session **turn_queue, int players_number, int *card_quantity_arr) { int i, j, key, player_deck_size, card_shortage_quantity, last_idx; const char *extracted_card = NULL; for(i = 0; i < players_number; ++i) { key = turn_queue[i]->player_position - 1; player_deck_size = card_quantity_arr[key]; if(player_deck_size < start_deck_size) { card_shortage_quantity = start_deck_size - player_deck_size; for(j = 0; j < card_shortage_quantity; ++j) { last_idx = *shuffled_cards_left-1; /* shuffled deck is empty */ if(last_idx == 0 || last_idx < 0) return; extracted_card = shuffled_deck[last_idx]; push_stack(&turn_queue[i]->deck, extracted_card); --*shuffled_cards_left; shuffled_deck[last_idx] = NULL; } } } } const char* extract_trump_card(const char **shuffled_deck, int *cards_left) { const char *trump_card = NULL; trump_card = shuffled_deck[0] ? shuffled_deck[0] : NULL; if(trump_card) { shuffled_deck[0] = NULL; --*cards_left; } return trump_card; } #if 0 const char* find_trump_suit(const char **shuffled_deck, int *cards_left) { const char *trump_suit = NULL; trump_suit = shuffled_deck[0] ? shuffled_deck[0] : NULL; if(trump_suit) { shuffled_deck[0] = NULL; trump_suit += strlen(trump_suit) - 1; --*cards_left; } return trump_suit; } #endif int convert_rank_to_int(const char *card) { int length; char str_rank[2]; length = strlen(card); /* 10 - the only one of its kind */ if(length == 3) return 10; str_rank[0] = card[0]; str_rank[1] = '\0'; switch(card[0]) { case 'J': return 11; case 'Q': return 12; case 'K': return 13; case 'A': return 14; default: return strtol(str_rank, NULL, 10); } return 0; } int find_lowest_trump(player_cards deck, const char *trump_suit) { int length, lowest_rank = 0, current_rank; const char *suit = NULL; while(deck) { length = strlen(deck->str); suit = deck->str + length - 1; if(*suit == *trump_suit) { current_rank = convert_rank_to_int(deck->str); if(!lowest_rank || lowest_rank > current_rank) lowest_rank = current_rank; } deck = deck->next; } return lowest_rank; } void shift_turn_queue_by_one(struct session **turn_queue, int size) { int i; struct session *tmp = turn_queue[0]; for(i = 1; i < size; ++i) turn_queue[i-1] = turn_queue[i]; turn_queue[i-1] = tmp; } void move_turn_queue_two_players_ahead(struct session **turn_queue, int size) { int i; for(i = 0; i < 2; ++i) shift_turn_queue_by_one(turn_queue, size); } void update_card_quantity_arr(struct server *serv) { int i, player_position_idx; for(i = 0; i < serv->max_sess_arr_size; ++i) if(serv->sess_arr[i]) { player_position_idx = serv->sess_arr[i]->player_position - 1; serv->cc.number_arr[player_position_idx] = find_out_card_quantity_in_deck(serv->sess_arr[i]->deck); } } struct game_info* get_new_game_info(int players_number, int *card_quantity_arr, int shuffled_cards_left, const char *trump_card, int position_whose_turn, struct card_queue *cq, struct cards_on_table *cot) { struct game_info *gi = malloc(sizeof(struct game_info)); gi->players_number = players_number; gi->card_quantity_arr = card_quantity_arr; gi->shuffled_cards_left = shuffled_cards_left; gi->trump_card = trump_card; gi->position_whose_turn = position_whose_turn; gi->cq = cq; gi->cot = cot; return gi; } void update_game_info(struct game_info *gi, int players_number, int shuffled_cards_left, int position_whose_turn) { gi->players_number = players_number; gi->shuffled_cards_left = shuffled_cards_left; gi->position_whose_turn = position_whose_turn; } int is_card_bit(const char *attack_card, const char *defend_card, const char *trump_suit) { int length, attack_rank, defend_rank; const char *attack_suit, *defend_suit; length = strlen(attack_card); attack_suit= attack_card + length - 1; length = strlen(defend_card); defend_suit = defend_card + length - 1; /* suits matched */ if(!strcmp(attack_suit, defend_suit)) { attack_rank = convert_rank_to_int(attack_card); defend_rank = convert_rank_to_int(defend_card); if(defend_rank > attack_rank) return 1; /* defender has a trump suit */ } else if(!strcmp(defend_suit, trump_suit)) return 1; return 0; } /* * analyze that each attacker card can be beat * TODO: free memory */ int check_defender_can_defend(struct card_queue *cq, player_cards deck, const char *trump_suit) { int is_bited_card; struct card_stack_item *next_defend_card; struct card_queue_item *next_attack_card; player_cards involved_cards; is_bited_card = 0; init_stack(&involved_cards); next_attack_card = NULL; while((next_attack_card = get_next_card_from_queue(cq, next_attack_card))) { /* get first defend card */ next_defend_card = NULL; next_defend_card = get_next_card_from_stack(deck, next_defend_card); /* stack traversal */ while(next_defend_card) { if(is_card_bit(next_attack_card->str, next_defend_card->str, trump_suit)) /* if card doesn't meet */ if(!find_card_in_stack(involved_cards, next_defend_card->str)) { push_stack(&involved_cards, next_defend_card->str); is_bited_card = 1; break; } get_next_card_from_stack(deck, next_defend_card); } if(is_bited_card) is_bited_card = 0; else return 0; } return 1; } static int check_matched_ranks(const char *attack_card, const char *not_defender_card) { int attack_rank, not_defender_rank; attack_rank = convert_rank_to_int(attack_card); not_defender_rank = convert_rank_to_int(not_defender_card); return attack_rank == not_defender_rank; } int check_someone_can_toss_card(struct session **turn_queue, int players_quantity, struct card_queue *cq, struct cards_on_table *cot) { int i, j; struct card_queue_item *attack_card_in_queue; struct card_stack_item *not_defender_card; for(i = 0; i < players_quantity; ++i) { /* skipping defender's cards */ if(i == 1) continue; /* checking card queue of attack cards */ attack_card_in_queue = NULL; while((attack_card_in_queue = get_next_card_from_queue(cq, attack_card_in_queue))) { not_defender_card = NULL; while((not_defender_card = get_next_card_from_stack(turn_queue[i]->deck, not_defender_card)) && !check_matched_ranks(attack_card_in_queue->str, not_defender_card->str)) {} if(not_defender_card) return 1; } /* checking cards on table */ for(j = cot->card_arr_idx; j >= 0; --j) { if(cot->card_arr[j][0] == '-' || cot->card_arr[j][0] == '\\') continue; not_defender_card = NULL; while((not_defender_card = get_next_card_from_stack(turn_queue[i]->deck, not_defender_card)) && !check_matched_ranks(cot->card_arr[j], not_defender_card->str)) {} if(not_defender_card) return 1; } } return 0; } /* is used to make the client's state tossing */ int check_player_can_toss_card(player_cards deck, struct cards_on_table *cot) { int i; struct card_stack_item *not_defender_card; /* checking cards on table */ for(i = cot->card_arr_idx; i >= 0; --i) { if(cot->card_arr[i][0] == '-' || cot->card_arr[i][0] == '\\') continue; not_defender_card = NULL; while((not_defender_card = get_next_card_from_stack(deck, not_defender_card)) && !check_matched_ranks(cot->card_arr[i], not_defender_card->str)) {} if(not_defender_card) return 1; } return 0; } int is_correct_tossing_card(const char *card, struct cards_on_table *cot) { int i; for(i = cot->card_arr_idx; i >= 0; --i) { if(cot->card_arr[i][0] == '-' || cot->card_arr[i][0] == '\\') continue; if(check_matched_ranks(cot->card_arr[i], card)) return 1; } return 0; } /* when defender cannot bit any card */ void put_all_cards_from_queue_to_table(struct cards_on_table *cot, struct card_queue *cq) { const char *card; while(!is_empty_queue(cq)) { card = pop_card_queue(cq); ++cot->card_arr_idx; cot->card_arr[cot->card_arr_idx] = card; ++cot->card_arr_idx; cot->card_arr[cot->card_arr_idx] = "\\"; ++cot->card_arr_idx; cot->card_arr[cot->card_arr_idx] = "-"; } } void put_one_card_from_queue_to_table(struct cards_on_table *cot, struct card_queue *cq) { const char *card; card = pop_card_queue(cq); ++cot->card_arr_idx; cot->card_arr[cot->card_arr_idx] = card; ++cot->card_arr_idx; cot->card_arr[cot->card_arr_idx] = "\\"; ++cot->card_arr_idx; cot->card_arr[cot->card_arr_idx] = "-"; } /* it used by defender to bit attack card */ void put_defender_card_on_table(struct cards_on_table *cot, const char *card) { cot->card_arr[cot->card_arr_idx] = card; } void move_all_cards_to_defender(struct cards_on_table *cot, player_cards *deck) { int i; #if 0 const char *card; while(!is_empty_queue(cq)) { card = pop_card_queue(cq); push_stack(deck, card); } #endif for(i = cot->card_arr_idx; i >= 0; --i) { if(cot->card_arr[i][0] == '-' || cot->card_arr[i][0] == '\\') continue; push_stack(deck, cot->card_arr[i]); } cot->card_arr_idx = i; } void remove_cards_from_table(struct cards_on_table *cot) { cot->card_arr_idx = -1; } int calculate_defense_card_quantity_on_table(const struct cards_on_table *cot) { int i, counter = 0; for(i = 0; i <= cot->card_arr_idx; ++i) { /* every 3 position meets a defender card */ if(!((i+1) % 3)) { if(!strcmp(cot->card_arr[i], "-")) continue; else ++counter; } } return counter; } int calculate_attack_card_quantity_on_table(const struct cards_on_table *cot) { int i, counter = 0; for(i = 0; i <= cot->card_arr_idx; ++i) if(i == 0 || !(i % 3)) ++counter; return counter; } int check_all_answers_were_received(const struct session **turn_queue, int size) { int i; for(i = 0; i < size; ++i) if(turn_queue[i]->tm == answer_wait) return 0; return 1; } int is_receiving_cards_limit(const struct cards_on_table *cot, player_cards defense_deck, const struct card_queue *cq) { int total_defense_cards, total_attack_cards; total_defense_cards = calculate_defense_card_quantity_on_table(cot); total_attack_cards = calculate_attack_card_quantity_on_table(cot); total_defense_cards += find_out_card_quantity_in_deck(defense_deck); total_attack_cards += find_out_card_quantity_in_cq(cq); if(total_defense_cards >= start_deck_size && total_attack_cards == start_deck_size) { return 1; } else if(total_defense_cards == total_attack_cards) return 1; return 0; }