From a2d696dea797faaa3157046c8ae89cd70e965bff Mon Sep 17 00:00:00 2001 From: scratko Date: Sat, 10 Aug 2024 02:46:56 +0300 Subject: Prefinal version Added client. Moved files to directories. --- server/server_game_process.c | 475 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 475 insertions(+) create mode 100644 server/server_game_process.c (limited to 'server/server_game_process.c') diff --git a/server/server_game_process.c b/server/server_game_process.c new file mode 100644 index 0000000..8bf4e60 --- /dev/null +++ b/server/server_game_process.c @@ -0,0 +1,475 @@ +#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; +} -- cgit v1.2.3