diff options
-rw-r--r-- | client/card_stack.c | 39 | ||||
-rw-r--r-- | client/card_stack.h | 2 | ||||
-rw-r--r-- | client/client.c | 34 | ||||
-rw-r--r-- | client/client.h | 1 | ||||
-rw-r--r-- | client/data_decryption.c | 12 | ||||
-rw-r--r-- | client/printing_game_frames.c | 18 | ||||
-rw-r--r-- | client/verification_client_input.c | 67 | ||||
-rw-r--r-- | server/card_stack.c | 9 | ||||
-rw-r--r-- | server/card_stack.h | 1 | ||||
-rw-r--r-- | server/server.c | 38 | ||||
-rw-r--r-- | server/server.h | 2 | ||||
-rw-r--r-- | server/server_data_processing.c | 38 | ||||
-rw-r--r-- | server/server_game_process.c | 121 | ||||
-rw-r--r-- | server/server_game_process.h | 2 |
14 files changed, 311 insertions, 73 deletions
diff --git a/client/card_stack.c b/client/card_stack.c index 5d0700b..d9dc273 100644 --- a/client/card_stack.c +++ b/client/card_stack.c @@ -81,11 +81,32 @@ void add_hint_letters_stack(player_cards deck) } } +static int check_no_attackers_cards_marked(player_cards deck) +{ + while(deck) { + if(deck->is_usable) + return 0; + deck = deck->next; + } + return 1; +} + +static void mark_all_card_stack(player_cards deck) +{ + player_cards tmp_deck = deck; + + while(tmp_deck) { + tmp_deck->is_usable = 1; + tmp_deck = tmp_deck->next; + } +} + void mark_card_for_attackers_stack(player_cards deck) { char *card = NULL, *found_card; struct card_stack_item *search_deck = NULL; int target_rank, found_rank; + player_cards tmp_begin_deck = deck; while(deck) { /* is the card already marked? */ @@ -103,12 +124,16 @@ void mark_card_for_attackers_stack(player_cards deck) } found_card = search_deck->str; found_rank = convert_rank_to_int(found_card); - if(found_rank == target_rank) + if(found_rank == target_rank) { + deck->is_usable = 1; search_deck->is_usable = 1; + } search_deck = search_deck->next; } deck = deck->next; } + 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, @@ -142,8 +167,8 @@ void mark_card_for_defenders_stack(player_cards deck, while(deck) { for(i = 0; i <= cot->card_arr_idx; ++i) - if((i == 0 || !(i % 3)) && is_card_beaten(cot->card_arr[i], - deck->str, trump_suit)) + if(((i == 0 || !(i % 3)) && cot->card_arr[i+2][0] == '-') && + is_card_beaten(cot->card_arr[i], deck->str, trump_suit)) { deck->is_usable = 1; break; @@ -179,15 +204,15 @@ void mark_card_for_tossing_stack(player_cards deck, struct cards_on_table *cot) deck = deck->next; } } - -int card_search_by_letter(player_cards deck, int letter) +/* rename: and_unmarked */ +char* card_search_by_letter(player_cards deck, int letter) { while(deck) { if(deck->tip == letter && deck->is_usable) { deck->is_usable = 0; - return 1; + return deck->str; } deck = deck->next; } - return 0; + return NULL; } diff --git a/client/card_stack.h b/client/card_stack.h index 7cb5798..ba973f4 100644 --- a/client/card_stack.h +++ b/client/card_stack.h @@ -24,6 +24,6 @@ void mark_card_for_defenders_stack(player_cards deck, struct cards_on_table *cot, char* trump_suit); void mark_card_for_tossing_stack(player_cards deck, struct cards_on_table *cot); -int card_search_by_letter(player_cards deck, int letter); +char* card_search_by_letter(player_cards deck, int letter); #endif diff --git a/client/client.c b/client/client.c index d932a51..4abcf7d 100644 --- a/client/client.c +++ b/client/client.c @@ -4,6 +4,7 @@ #include <unistd.h> #include <stdlib.h> #include <string.h> +#include <stdio.h> /* test */ #include "client.h" #include "data_decryption.h" @@ -15,15 +16,23 @@ static const int port = 8082; static void get_data_from_server(struct client *cl, fd_set *readfds) { + int i; int update_info = 0; /* pointer to delimeter (:) that is behind extract data */ char *end_p; if(FD_ISSET(cl->fd, readfds)) { - read(cl->fd, cl->buffer, max_buffer_size); + if(!cl->data_left_in_buffer) { + cl->data_left_in_buffer = read(cl->fd, cl->buffer, max_buffer_size); + printf("%d\n", cl->data_left_in_buffer); + for(i = 0; i < cl->data_left_in_buffer; ++i) + putchar(cl->buffer[i]); + putchar('\n'); + } decrypt_set_state(cl, &end_p); update_info = 1; cl->display_new_frame = 1; + cl->pending_server_response = 0; } if(update_info) { switch(cl->state) { @@ -50,13 +59,20 @@ static void get_data_from_server(struct client *cl, fd_set *readfds) decrypt_set_card_queue(cl, end_p+1); break; case card_acceptance_status: - decrypt_set_card_acceptance_status(cl, cl->buffer); + decrypt_set_card_acceptance_status(cl, end_p+1); break; /* no data to extract */ case tossing_limit_status: default: {} } + for(i = 0; cl->buffer[i] != '\n'; ++i) + {} + if((cl->buffer+i - cl->buffer + 1) != cl->data_left_in_buffer) { + cl->data_left_in_buffer -= i + 1; + memmove(cl->buffer, cl->buffer+i+1, cl->data_left_in_buffer); + } else + cl->data_left_in_buffer = 0; } } @@ -66,7 +82,7 @@ static void prepare_tips_for_client(struct client *cl) if(!is_empty_stack(cl->deck)) add_hint_letters_stack(cl->deck); - +/* TODO: clear marked cards ??? */ switch(cl->state) { case attack: mark_card_for_attackers_stack(cl->deck); @@ -126,7 +142,7 @@ static void change_client_frame(struct client *cl) static void send_data_to_server(struct client *cl, fd_set *readfds) { - int input_result; + int input_result = 0; if(FD_ISSET(0, readfds)) { /* 0 - stdin */ read(0, cl->buffer, max_buffer_size); @@ -181,9 +197,11 @@ int main_loop(struct client *cl) if(check_tracking_client_input(cl->state, cl->pending_server_response)) FD_SET(0, &readfds); - select_result = select(cl->fd + 1, &readfds, NULL, NULL, NULL); - if(select_result == -1) - return 2; + if(!cl->data_left_in_buffer) { + select_result = select(cl->fd + 1, &readfds, NULL, NULL, NULL); + if(select_result == -1) + return 2; + } get_data_from_server(cl, &readfds); prepare_tips_for_client(cl); if(cl->display_new_frame) @@ -210,6 +228,7 @@ static void init_client(struct client *cl) cl->position_whose_turn = 0; cl->display_new_frame = 0; cl->all_input_cards_accepted = 0; + cl->data_left_in_buffer = 0; } /* @@ -222,6 +241,7 @@ static int connect_to_server(struct client *cl) struct sockaddr_in addr; cl->fd = socket(AF_INET, SOCK_STREAM, 0); + if(cl->fd == -1) return 0; addr.sin_family = AF_INET; diff --git a/client/client.h b/client/client.h index f73cdce..9bdd8cc 100644 --- a/client/client.h +++ b/client/client.h @@ -66,6 +66,7 @@ struct client { int position_whose_turn; int display_new_frame; int all_input_cards_accepted; + int data_left_in_buffer; }; #endif diff --git a/client/data_decryption.c b/client/data_decryption.c index 2d10561..b445454 100644 --- a/client/data_decryption.c +++ b/client/data_decryption.c @@ -4,6 +4,7 @@ #include <stdlib.h> #include <string.h> +#include <unistd.h> void decrypt_set_state(struct client *cl, char **end_p) { @@ -24,11 +25,9 @@ static void decrypt_set_trump_card(struct client *cl, char *start_p, { int i; - for(i = 0; *start_p != '\0'; ++start_p, ++i) + for(i = 0; *start_p != ':'; ++start_p, ++i) cl->trump_card[i] = *start_p; cl->trump_card[i] = '\0'; - /* move to : */ - ++start_p; *end_p = start_p; } @@ -65,7 +64,7 @@ void decrypt_set_base_info(struct client *cl, char *start_p, char **end_p) i = 0, j = 0; for(start_p = *end_p + 1; *start_p != ':'; ++start_p) { /* empty table */ - if(*start_p == '0') { + if(*start_p == '=') { /* to delimiter : */ ++start_p; i = -1; @@ -94,7 +93,7 @@ void decrypt_set_base_info(struct client *cl, char *start_p, char **end_p) for(++start_p, i = 0; *start_p != ':' && *start_p != '\n'; ++start_p) { /* empty deck */ - if(*start_p == '0') { + if(*start_p == '=') { i = -1; /* to delimiter ':' or '\n' */ ++start_p; @@ -107,6 +106,7 @@ void decrypt_set_base_info(struct client *cl, char *start_p, char **end_p) strcpy(card, tmp_card); push_stack(&cl->deck, card); i = 0; + continue; } tmp_card[i] = *start_p; ++i; @@ -132,7 +132,7 @@ void decrypt_set_card_queue(struct client *cl, char *start_p) for(i = 0, j = 0; *start_p != '\n'; ++start_p) { /* empty queue */ - if(*start_p == '0') { + if(*start_p == '=') { i = -1; break; } diff --git a/client/printing_game_frames.c b/client/printing_game_frames.c index 38f1a78..f75cec5 100644 --- a/client/printing_game_frames.c +++ b/client/printing_game_frames.c @@ -5,17 +5,17 @@ void pgf_first_player() { - printf("=======================================" - " You're the first player" - "Waiting for other players to connect..." + printf("=======================================\n" + " You're the first player\n" + "Waiting for other players to connect...\n" "=======================================\n"); } void pgf_confirmation_waiting(int total_players) { - printf("=======================================" - " To start game press <Enter> key " - "Connected players: %u/8 " + printf("=======================================\n" + " To start game press <Enter> key \n" + "Connected players: %u/8 \n" "=======================================\n", total_players); } @@ -24,7 +24,7 @@ void pgf_table(struct client *cl) struct card_stack_item *deck = NULL; int i; - for(i = 0; i < cl->cc.number_arr_idx; ++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 ? '*' : ' ', @@ -41,7 +41,8 @@ void pgf_table(struct client *cl) if(cl->state == defense_expectation) for(i = 0; i <= cl->cq.card_arr_idx; ++i) printf(" %s \\ -\n", cl->cq.card_arr[i]); - printf("\n\n"); + if(cl->cot.card_arr_idx != -1) + printf("\n\n"); /* ================ player's deck ================ */ deck = cl->deck; i = 0; @@ -70,6 +71,7 @@ void pgf_suggestions(struct client *cl) deck = deck->next; } printf(" > "); + fflush(stdout); } void pgf_select_idle_mode_message(enum client_states state) diff --git a/client/verification_client_input.c b/client/verification_client_input.c index 2134f30..1530387 100644 --- a/client/verification_client_input.c +++ b/client/verification_client_input.c @@ -1,7 +1,15 @@ #include "verification_client_input.h" +#include "card_handling.h" #include <stdio.h> #include <unistd.h> +#include <string.h> + +enum { + output_buffer_size = 1024 +}; + +static char output_buffer[output_buffer_size]; /* * 1 - response received @@ -18,29 +26,70 @@ int vci_confirmation_waiting(int fd, char *buffer) return 0; } +/* + * example: A#\A^\Av\'\n' + * or (while tossing): '\n' + */ int vci_attack_or_tossing(int fd, char *buffer, player_cards deck, enum client_states state) { - int i; + int i, free_pos = 0; + char * card = NULL; - if(state == tossing && buffer[0] == '\n') /* cancel card tossing */ + if(state == tossing && buffer[0] == '\n') { /* cancel card tossing */ + write(fd, buffer, 1); return 1; + } for(i = 0; buffer[i] != '\n'; ++i) - if(!card_search_by_letter(deck, buffer[i])) { + if((card = card_search_by_letter(deck, buffer[i])) != NULL) { +#if 0 + if(!rank) + rank = convert_rank_to_int(card); + if(rank == convert_rank_to_int(card)) { +#endif + strncpy(output_buffer + free_pos, card, strlen(card)); + free_pos += strlen(card); + output_buffer[free_pos] = '\\'; + ++free_pos; +#if 0 + } else { + printf("incorrect input\n"); + return 0; + } +#endif + } else { printf("incorrect input\n"); return 0; } + output_buffer[free_pos] = '\n'; + write(fd, output_buffer, free_pos+1); return 1; } - +/* + * example: 5v'\n' + * or: '\n' + */ int vci_defense(int fd, char *buffer, player_cards deck) { - if(buffer[0] == '\n') /* the player does not want to keep the defense */ + int last_idx; + char *card = NULL; + + if(buffer[0] == '\n') { /* the player does not want to keep the defense */ + write(fd, buffer, 1); return 1; - if(!card_search_by_letter(deck, buffer[0])) - return 0; - if(buffer[1] != '\n') + } + if(buffer[1] != '\n') { + printf("incorrect input\n"); return 0; - return 1; + } + if((card = card_search_by_letter(deck, buffer[0])) != NULL) { + strcpy(output_buffer, card); + last_idx = strlen(card); + output_buffer[last_idx] = '\n'; + write(fd, output_buffer, last_idx+1); + return 1; + } + /* card is not found in the deck or cannot be used */ + return 0; } diff --git a/server/card_stack.c b/server/card_stack.c index aa8af71..c7c18d9 100644 --- a/server/card_stack.c +++ b/server/card_stack.c @@ -59,6 +59,15 @@ const char* remove_card_from_stack(player_cards *deck, const char *str) return 0; } +const char* pop_stack(player_cards *deck) +{ + struct card_stack_item *tmp; + + tmp = *deck; + *deck = (*deck)->next; + free(tmp); +} + struct card_stack_item* get_next_card_from_stack(player_cards deck, player_cards prev) { diff --git a/server/card_stack.h b/server/card_stack.h index d380ded..321cbf0 100644 --- a/server/card_stack.h +++ b/server/card_stack.h @@ -17,5 +17,6 @@ const char* remove_card_from_stack(player_cards *deck, const char *str); struct card_stack_item* get_next_card_from_stack(player_cards deck, player_cards prev); int find_card_in_stack(player_cards involved_cards, const char *str); +const char* pop_stack(player_cards *deck); #endif diff --git a/server/server.c b/server/server.c index 0a2bd0f..b2f1c3b 100644 --- a/server/server.c +++ b/server/server.c @@ -7,6 +7,7 @@ #include <fcntl.h> #include <syslog.h> #include <time.h> +#include <netinet/tcp.h> #include "server.h" #include "server_data_processing.h" @@ -34,6 +35,7 @@ static int accept_client(struct server *serv) struct session *new_session; socklen_t len = sizeof(addr); fd = accept(serv->listen_socket, (struct sockaddr*) &addr, &len); + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (int[]){1}, sizeof(int)); if(fd == -1) return -1; @@ -395,6 +397,8 @@ static void determine_server_state(struct server *serv) case start_game: set_state_for_client(serv, attack); set_whose_turn(serv, attack); + update_game_info(serv->gi, serv->connected_players_counter, + serv->shuffled_deck_size, serv->position_whose_turn); set_record_status_for_all(serv); serv->state = attack_phase_out; break; @@ -418,6 +422,7 @@ static void determine_server_state(struct server *serv) break; case table: if(serv->turn_queue[1]->defense_lost) { + clear_defense_lost_status(serv->turn_queue[1]); move_all_cards_to_defender(&serv->cot, &serv->turn_queue[1]->deck); move_turn_queue_two_players_ahead(serv->turn_queue, serv->connected_players_counter); @@ -430,10 +435,18 @@ static void determine_server_state(struct server *serv) set_record_status_for_all(serv); set_state_for_client(serv, attack); set_whose_turn(serv, attack); + /* + * update the number of cards to determine how many cards + * a player still needs to add + */ update_card_quantity_arr(serv); deal_cards(serv->shuffled_deck, &serv->shuffled_deck_size, serv->turn_queue, serv->connected_players_counter, serv->cc.number_arr); + /* update the card count after giving out */ + update_card_quantity_arr(serv); + update_game_info(serv->gi, serv->connected_players_counter, + serv->shuffled_deck_size, serv->position_whose_turn); serv->state = attack_phase_out; break; case defense_phase_out: @@ -480,7 +493,7 @@ static int accept_new_player(struct server *serv) } static void set_up_player_tracking(struct server *serv, fd_set *readfds, - fd_set *writefds) + fd_set *writefds, int *maxfd) { int i; for(i = 0; i < serv->max_sess_arr_size; ++i) { @@ -489,11 +502,14 @@ static void set_up_player_tracking(struct server *serv, fd_set *readfds, switch(serv->state) { case first_player: - if(serv->sess_arr[i]->record) + if(serv->sess_arr[i]->record) { FD_SET(i, writefds); + *maxfd = i > *maxfd ? i : *maxfd; + } break; case confirmation_waiting: FD_SET(i, readfds); + *maxfd = i > *maxfd ? i : *maxfd; if(serv->sess_arr[i]->record) FD_SET(i, writefds); break; @@ -502,21 +518,30 @@ static void set_up_player_tracking(struct server *serv, fd_set *readfds, case table: case defense_phase_out: case tossing_phase_out: - if(serv->sess_arr[i]->record) + if(serv->sess_arr[i]->record) { FD_SET(i, writefds); + *maxfd = i > *maxfd ? i : *maxfd; + } break; case attack_phase_in: - if(serv->sess_arr[i]->state == attack) + if(serv->sess_arr[i]->state == attack) { FD_SET(i, readfds); + *maxfd = i > *maxfd ? i : *maxfd; + } break; case defense_phase_in: - if(serv->sess_arr[i]->state == defense) + if(serv->sess_arr[i]->state == defense) { FD_SET(i, readfds); + *maxfd = i > *maxfd ? i : *maxfd; + } break; case tossing_phase_in: if(serv->sess_arr[i]->state == tossing && serv->sess_arr[i]->tm == answer_wait) + { FD_SET(i, readfds); + *maxfd = i > *maxfd ? i : *maxfd; + } break; case no_players: {} @@ -646,7 +671,7 @@ int main_loop(struct server *serv) maxfd = serv->listen_socket; } - set_up_player_tracking(serv, &readfds, &writefds); + set_up_player_tracking(serv, &readfds, &writefds, &maxfd); select_result = select(maxfd + 1, &readfds, &writefds, NULL, NULL); if(select_result == -1) @@ -677,7 +702,6 @@ static int init_server(struct server *serv, int port) opt = 1; setsockopt(serv->listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); diff --git a/server/server.h b/server/server.h index 46c965b..86e0fca 100644 --- a/server/server.h +++ b/server/server.h @@ -7,7 +7,7 @@ enum { max_buffer_size = 4096, listen_qlen = 32, - init_sess_arr_size = 32 + init_sess_arr_size = 12 /* it was 32 */ }; enum { diff --git a/server/server_data_processing.c b/server/server_data_processing.c index 30953bf..b7b2374 100644 --- a/server/server_data_processing.c +++ b/server/server_data_processing.c @@ -145,12 +145,12 @@ static void copy_base_info(int *free_pos, struct game_info *gi, if(gi->cot->card_arr_idx != -1) copy_cards_on_table(free_pos, *gi->cot); else - *free_pos += sprintf(output_buffer + *free_pos, "0:"); + *free_pos += sprintf(output_buffer + *free_pos, "=:"); if(!is_empty_stack(deck)) copy_own_deck(free_pos, deck); else - *free_pos += sprintf(output_buffer + *free_pos, "0:"); + *free_pos += sprintf(output_buffer + *free_pos, "=:"); } int print_game_part(const struct session *client, struct game_info *gi) @@ -186,7 +186,7 @@ int print_game_part(const struct session *client, struct game_info *gi) gi->position_whose_turn); /* copying card queue */ if(is_empty_queue(gi->cq)) - free_pos += sprintf(output_buffer + free_pos, "0:"); + free_pos += sprintf(output_buffer + free_pos, "=:"); else copy_card_queue(&free_pos, gi->cq); *(output_buffer + free_pos-1) = '\n'; @@ -207,6 +207,10 @@ static int is_receiving_cards_limit(int total_defense_cards, int total_attack_ca } #endif + +/* + * example: 7v\2#\A^\'\n' + */ int get_cards_from_attacker(struct session *client, const struct cards_on_table *cot, const player_cards defense_deck, @@ -219,9 +223,13 @@ int get_cards_from_attacker(struct session *client, const char *stack_card = NULL; read_result = read_from_client(client->fd, client->buffer, max_buffer_size); + printf("%d\n", read_result); + for(i = 0; i < read_result; ++i) + putchar(client->buffer[i]); + putchar('\n'); if(!read_result) return read_result; - for(i = 0, j = 0; i < read_result && client->buffer[i] != '\n'; ++i) { + for(i = 0, j = 0; i < read_result; ++i) { if(client->buffer[i] == '\\') { given_card[j] = '\0'; j = 0; @@ -249,6 +257,8 @@ int get_cards_from_attacker(struct session *client, * 1 - card was bited, not bited, or * defender didn't want to continue defense phase * + * example: 5v'\n' + * or: '\n' */ int get_card_from_defender(struct session *client, struct cards_on_table *cot, const char * trump_suit) @@ -258,12 +268,16 @@ int get_card_from_defender(struct session *client, struct cards_on_table *cot, const char *stack_card = NULL; read_result = read_from_client(client->fd, client->buffer, max_buffer_size); + printf("%d\n", read_result); + for(i = 0; i < read_result; ++i) + putchar(client->buffer[i]); + putchar('\n'); if(!read_result) return read_result; + if(client->buffer[0] == '\n') + return 1; for(i = 0; i < read_result && client->buffer[i] != '\n'; ++i) given_card[i] = client->buffer[i]; - if(given_card[0] == '\n') - return 1; given_card[i] = '\0'; if(is_card_bit(cot->card_arr[cot->card_arr_idx-2], given_card, trump_suit)){ stack_card = remove_card_from_stack(&client->deck, given_card); @@ -280,6 +294,7 @@ int get_card_from_defender(struct session *client, struct cards_on_table *cot, * 3 - player refused to toss the card * * example: 10#\A^\7v\'\n' + * or: '\n' */ int get_cards_from_tossing_player(struct session *client, const player_cards defense_deck, @@ -293,14 +308,15 @@ int get_cards_from_tossing_player(struct session *client, const char *stack_card = NULL; read_result = read_from_client(client->fd, client->buffer, max_buffer_size); + printf("%d\n", read_result); + for(i = 0; i < read_result; ++i) + putchar(client->buffer[i]); + putchar('\n'); if(!read_result) return read_result; for(i = 0, j = 0; i < read_result; ++i) { if(client->buffer[i] == '\\') { - /* cancellation */ - if(given_card[0] == '\n') - return 3; /* tossing limit was set */ if(client->tm == cancel) { /* it's impossible to accept cards due to tossing limit */ @@ -326,6 +342,10 @@ int get_cards_from_tossing_player(struct session *client, given_card[j] = client->buffer[i]; ++j; } + /* cancellation */ + if(client->buffer[0] == '\n') + return 3; + /* 7 -- state for result of received cards */ data_length = sprintf(output_buffer, "%d:%s\n", card_acceptance_status, all_cards_received_status ? "all" : "not all"); diff --git a/server/server_game_process.c b/server/server_game_process.c index 8bf4e60..46a9535 100644 --- a/server/server_game_process.c +++ b/server/server_game_process.c @@ -12,7 +12,7 @@ static const char *basic_deck[deck_size] = { "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", + "J%", "Q%", "K%", "A%", "2v", "3v", "4v", "5v", "6v", "7v", "8v", "9v", "10v", "Jv", "Qv", "Kv", "Av" }; @@ -66,7 +66,7 @@ void deal_cards(const char **shuffled_deck, int *shuffled_cards_left, 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) + if(last_idx < 0) return; extracted_card = shuffled_deck[last_idx]; push_stack(&turn_queue[i]->deck, extracted_card); @@ -81,9 +81,10 @@ 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; + trump_card = shuffled_deck[*cards_left-1] ? + shuffled_deck[*cards_left-1] : NULL; if(trump_card) { - shuffled_deck[0] = NULL; + shuffled_deck[*cards_left-1] = NULL; --*cards_left; } return trump_card; @@ -226,6 +227,56 @@ int is_card_bit(const char *attack_card, const char *defend_card, return 1; return 0; } + +static void find_out_trump_cards_in_deck(player_cards *trump_cards, + player_cards deck, + const char *trump_suit) +{ + const char *suit = NULL, *card = NULL; + + while(deck) { + card = deck->str; + suit= card + strlen(card) - 1; + if(*suit == *trump_suit) + push_stack(trump_cards, card); + deck = deck->next; + } +} + +static int is_same_suit_and_not_meet(player_cards involved_cards, + struct card_stack_item *defend_card, + struct card_queue_item *attack_card) + +{ + int length; + const char *attack_suit, *defend_suit; + + if(!find_card_in_stack(involved_cards, defend_card->str)) { + length = strlen(attack_card->str); + attack_suit= attack_card->str + length - 1; + length = strlen(defend_card->str); + defend_suit = defend_card->str + length - 1; + return *attack_suit == *defend_suit; + } + return 0; +} + +static int trump_cards_left_uncovered(player_cards remaining_cards, + const char *trump_suit) +{ + const char *suit; + const char *card = NULL; + + while(remaining_cards) { + card = remaining_cards->str; + suit = card + strlen(card) - 1; + if(*suit == *trump_suit) + return 1; + remaining_cards = remaining_cards->next; + } + return 0; +} + /* * analyze that each attacker card can be beat * TODO: free memory @@ -233,13 +284,18 @@ int is_card_bit(const char *attack_card, const char *defend_card, int check_defender_can_defend(struct card_queue *cq, player_cards deck, const char *trump_suit) { - int is_bited_card; + int current_rank = 0, min_rank = 0; struct card_stack_item *next_defend_card; struct card_queue_item *next_attack_card; - player_cards involved_cards; + const char* card_with_min_rank = NULL; + + player_cards involved_cards, trump_cards, remaining_attack_cards; - is_bited_card = 0; init_stack(&involved_cards); + init_stack(&trump_cards); + init_stack(&remaining_attack_cards); + + find_out_trump_cards_in_deck(&trump_cards, deck, trump_suit); next_attack_card = NULL; while((next_attack_card = get_next_card_from_queue(cq, next_attack_card))) { @@ -247,23 +303,47 @@ int check_defender_can_defend(struct card_queue *cq, next_defend_card = NULL; next_defend_card = get_next_card_from_stack(deck, next_defend_card); - /* stack traversal */ + card_with_min_rank = NULL; + min_rank = 0; + 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; + { + if(is_same_suit_and_not_meet(involved_cards, next_defend_card, + next_attack_card)) + { + current_rank = convert_rank_to_int(next_defend_card->str); + if(!card_with_min_rank || min_rank > current_rank) { + card_with_min_rank = next_defend_card->str; + min_rank = current_rank; + } } - get_next_card_from_stack(deck, next_defend_card); + } + next_defend_card = get_next_card_from_stack(deck, next_defend_card); } - if(is_bited_card) - is_bited_card = 0; - else - return 0; + if(card_with_min_rank) { + push_stack(&involved_cards, card_with_min_rank); + if(find_card_in_stack(trump_cards, card_with_min_rank)) + remove_card_from_stack(&trump_cards, card_with_min_rank); + } else + push_stack(&remaining_attack_cards, next_attack_card->str); } + /* + * there are trump attacking uncovered cards remaining + * if the defender also has trump cards, they are of a lower rank + */ + if(trump_cards_left_uncovered(remaining_attack_cards, trump_suit)) + return 0; + while(remaining_attack_cards) { + if(!is_empty_stack(trump_cards)) { + pop_stack(&trump_cards); + pop_stack(&remaining_attack_cards); + } else + break; + } + if(!is_empty_stack(remaining_attack_cards)) + return 0; return 1; } @@ -473,3 +553,8 @@ int is_receiving_cards_limit(const struct cards_on_table *cot, return 1; return 0; } + +void clear_defense_lost_status(struct session *defender) +{ + defender->defense_lost = 0; +} diff --git a/server/server_game_process.h b/server/server_game_process.h index 8891a56..9338c25 100644 --- a/server/server_game_process.h +++ b/server/server_game_process.h @@ -75,4 +75,6 @@ int check_all_answers_were_received(const struct session **turn_queue, int is_receiving_cards_limit(const struct cards_on_table *cot, player_cards defense_deck, const struct card_queue *cq); +void clear_defense_lost_status(struct session *defender); + #endif |