From 9970a2275a56d7835ba0c12a8586dc25cf7ec1cf Mon Sep 17 00:00:00 2001 From: scratko Date: Sun, 18 Aug 2024 01:33:08 +0300 Subject: Global fixes v4.0 Removed unnecessary comments. Added resource cleanup for client and server. Changed queue display. Added player indicator. It's possible to quit the game while typing or waiting for a connection. Fixed a bug with determining the limit of card tossing. --- client/card_stack.c | 65 -------------------------------------- client/client.c | 42 +++++++++++++++++------- client/printing_game_frames.c | 45 ++++++++++++++++++++------ client/verification_client_input.c | 10 ++++-- 4 files changed, 73 insertions(+), 89 deletions(-) (limited to 'client') diff --git a/client/card_stack.c b/client/card_stack.c index 6f0a673..fc4057c 100644 --- a/client/card_stack.c +++ b/client/card_stack.c @@ -38,36 +38,6 @@ int is_empty_stack(player_cards deck) return deck == NULL; } -#if 0 -static 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; -} -#endif - void add_hint_letters_stack(player_cards deck) { unsigned char letter = 'a'; @@ -145,30 +115,6 @@ void mark_card_for_attackers_stack(player_cards deck) if(check_no_attackers_cards_marked(tmp_begin_deck)) mark_all_card_stack(tmp_begin_deck); } -#if 0 -static int is_card_beaten(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; -} -#endif void mark_card_for_defenders_stack(player_cards deck, struct cards_on_table *cot, char *trump_suit) @@ -186,17 +132,6 @@ void mark_card_for_defenders_stack(player_cards deck, deck = deck->next; } } -#if 0 -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; -} -#endif void mark_card_for_tossing_stack(player_cards deck, struct cards_on_table *cot) { diff --git a/client/client.c b/client/client.c index 5d49e1a..66bfb01 100644 --- a/client/client.c +++ b/client/client.c @@ -4,7 +4,7 @@ #include #include #include -#include /* test */ +#include /* for debug */ #include "client.h" #include "data_decryption.h" @@ -12,7 +12,13 @@ #include "verification_client_input.h" static const char *ip = "127.0.0.1"; -static const int port = 8082; +static const int port = 1025; + +static void clean_up_resources(struct client *cl) +{ + free(cl->cc.number_arr); + clear_stack(&cl->deck); +} static void get_data_from_server(struct client *cl, fd_set *readfds) { @@ -24,9 +30,12 @@ static void get_data_from_server(struct client *cl, fd_set *readfds) if(FD_ISSET(cl->fd, readfds)) { if(!cl->data_left_in_buffer) { cl->data_left_in_buffer = read(cl->fd, cl->buffer, max_buffer_size); - /* end of file -- closed connection */ - if(!cl->data_left_in_buffer) + /* end of file -- closed connection (from server) */ + if(!cl->data_left_in_buffer) { + clean_up_resources(cl); + pgf_disconnect(); exit(0); + } #ifdef DEBUG printf("%d\n", cl->data_left_in_buffer); for(i = 0; i < cl->data_left_in_buffer; ++i) @@ -47,13 +56,13 @@ static void get_data_from_server(struct client *cl, fd_set *readfds) cl->total_players = decrypt_get_number(end_p+1, &end_p); break; case display_only_table: - case attack: - case defense: case tossing_expectation: case tossing: /* last arg will contain pointer to '\n' */ decrypt_set_base_info(cl, end_p+1, &end_p); break; + case attack: + case defense: case attack_expectation: decrypt_set_base_info(cl, end_p+1, &end_p); decrypt_set_position_whose_turn(cl, end_p+1, &end_p); @@ -163,14 +172,26 @@ static void change_client_frame(struct client *cl) } } +static int check_users_exti(enum client_states state, const char *buffer, + int size) +{ + if((state == first_player || state == confirmation_waiting) && + size == 2 && (buffer[0] == 'q' && buffer[1] == '\n')) + return 1; + + return size == 3 && !strncmp(buffer, "qq", 2) && buffer[2] == '\n'; +} + static void send_data_to_server(struct client *cl, fd_set *readfds) { - int input_result = 0; + int input_result = 0, data_size; if(FD_ISSET(0, readfds)) { /* 0 - stdin */ - read(0, cl->buffer, max_buffer_size); - if(cl->buffer[0] == 'q' && cl->buffer[1] == 'q') { + data_size = read(0, cl->buffer, max_buffer_size); + if(check_users_exti(cl->state, cl->buffer, data_size)) { close(cl->fd); + clean_up_resources(cl); + pgf_disconnect(); exit(0); } @@ -202,6 +223,7 @@ static int check_tracking_client_input(enum client_states state, return 0; switch(state) { + case first_player: case confirmation_waiting: case attack: case defense: @@ -246,9 +268,7 @@ static void init_client(struct client *cl) cl->total_cards_left = 0; cl->player_position = 0; cl->cc.number_arr = NULL; -#if 0 cl->cc.number_arr_idx = -1; -#endif cl->cot.card_arr_idx = -1; cl->deck = NULL; cl->pending_server_response = 0; diff --git a/client/printing_game_frames.c b/client/printing_game_frames.c index bda1208..6b2131a 100644 --- a/client/printing_game_frames.c +++ b/client/printing_game_frames.c @@ -2,6 +2,7 @@ #include "card_stack.h" #include +#include void pgf_new_frame() { @@ -34,29 +35,39 @@ void pgf_first_player() printf("=======================================\n" " You're the first player\n" "Waiting for other players to connect...\n" + " Press q to exit\n" "=======================================\n"); } void pgf_confirmation_waiting(int total_players) { printf("=======================================\n" - " To start game press key \n" - " Connected players: %u/8 \n" + " To start game press key\n" + " Connected players: %u/8\n" + " Press q to exit\n" "=======================================\n", total_players); } +static int move_indication_condition(const struct client *cl, + int current_player) +{ + return + current_player == cl->position_whose_turn && + (cl->state == attack_expectation || cl->state == defense_expectation || + cl->state == attack || cl->state == defense || + (cl->state == spectator && (cl->sp_mode == spectator_attack || + cl->sp_mode == spectator_defense))); +} + void pgf_table(struct client *cl) { struct card_stack_item *deck = NULL; int i; for(i = 0; i <= cl->cc.number_arr_idx; ++i) - /* printing who will move */ - if(cl->state == attack_expectation || cl->state == defense_expectation) - printf("<%c%u > ", cl->position_whose_turn-1 == i ? '*' : ' ', - cl->cc.number_arr[i]); - else - printf("< %u > ", cl->cc.number_arr[i]); + printf("<%s %u %c> ", cl->player_position == i+1 ? "YOU" : " ", + cl->cc.number_arr[i], move_indication_condition(cl, i+1) ? + '*' : ' '); printf(" %s [ %u ]", cl->trump_card, cl->total_cards_left); printf("\n\n\n"); /* ================= cards on table ================ */ @@ -64,7 +75,7 @@ void pgf_table(struct client *cl) printf(" %s %s %s\n", cl->cot.card_arr[i], cl->cot.card_arr[i+1], cl->cot.card_arr[i+2]); /* for the defender, the cards in the queue are hidden */ - if(cl->state == defense_expectation) + if(cl->state == defense_expectation || cl->state == spectator) for(i = 0; i <= cl->cq.card_arr_idx; ++i) printf(" %s \\ -\n", cl->cq.card_arr[i]); if(cl->cot.card_arr_idx != -1) @@ -88,6 +99,7 @@ void pgf_suggestions(struct client *cl) { struct card_stack_item *deck = NULL; + printf("qq - exit the game\n"); if(cl->state == attack || cl->state == tossing) printf("you can specify more than one card\n"); deck = cl->deck; @@ -152,7 +164,20 @@ void pgf_game_result(int durak_position) "=======================================\n", durak_position); } +static void clear_input() +{ + int key; + + while((key = getchar()) != '\n') + {} +} + void pgf_disconnect() { - printf("Server connection disconnected\n"); + char key; + + printf("Server connection disconnected\n" + "Press to close program\n"); + while((key = getchar()) != '\n') + clear_input(); } diff --git a/client/verification_client_input.c b/client/verification_client_input.c index 171cd64..fa88b54 100644 --- a/client/verification_client_input.c +++ b/client/verification_client_input.c @@ -39,6 +39,7 @@ int vci_attack_or_tossing(int fd, char *buffer, player_cards deck, if(state == tossing && buffer[0] == '\n') { /* cancel card tossing */ write(fd, buffer, 1); + printf("skipping the card toss\n"); return 1; } @@ -72,9 +73,9 @@ int vci_attack_or_tossing(int fd, char *buffer, player_cards deck, ++free_pos; } if(state == attack && buffer[0] == '\n') { - printf("incorrect input\n> "); - fflush(stdout); - return 0; + printf("incorrect input\n> "); + fflush(stdout); + return 0; } output_buffer[free_pos] = '\n'; write(fd, output_buffer, free_pos+1); @@ -92,6 +93,7 @@ int vci_defense(int fd, char *buffer, player_cards deck) if(buffer[0] == '\n') { /* the player does not want to keep the defense */ write(fd, buffer, 1); + printf("accepting cards\n"); return 1; } if(buffer[1] != '\n') { @@ -107,5 +109,7 @@ int vci_defense(int fd, char *buffer, player_cards deck) return 1; } /* card is not found in the deck or cannot be used */ + printf("incorrect input\n> "); + fflush(stdout); return 0; } -- cgit v1.2.3