diff options
-rw-r--r-- | client/Makefile | 18 | ||||
-rw-r--r-- | client/card_handling.c | 64 | ||||
-rw-r--r-- | client/card_handling.h | 9 | ||||
-rw-r--r-- | client/card_stack.c | 193 | ||||
-rw-r--r-- | client/card_stack.h | 29 | ||||
-rw-r--r-- | client/client.c | 245 | ||||
-rw-r--r-- | client/client.h | 71 | ||||
-rw-r--r-- | client/data_decryption.c | 169 | ||||
-rw-r--r-- | client/data_decryption.h | 14 | ||||
-rw-r--r-- | client/printing_game_frames.c | 104 | ||||
-rw-r--r-- | client/printing_game_frames.h | 14 | ||||
-rw-r--r-- | client/verification_client_input.c | 46 | ||||
-rw-r--r-- | client/verification_client_input.h | 12 | ||||
-rw-r--r-- | server/Makefile (renamed from Makefile) | 0 | ||||
-rw-r--r-- | server/card_queue.c (renamed from card_queue.c) | 0 | ||||
-rw-r--r-- | server/card_queue.h (renamed from card_queue.h) | 0 | ||||
-rw-r--r-- | server/card_stack.c (renamed from card_stack.c) | 0 | ||||
-rw-r--r-- | server/card_stack.h (renamed from card_stack.h) | 0 | ||||
-rw-r--r-- | server/server.c (renamed from server.c) | 130 | ||||
-rw-r--r-- | server/server.h (renamed from server.h) | 21 | ||||
-rw-r--r-- | server/server_data_processing.c (renamed from server_data_processing.c) | 121 | ||||
-rw-r--r-- | server/server_data_processing.h (renamed from server_data_processing.h) | 5 | ||||
-rw-r--r-- | server/server_game_process.c (renamed from server_game_process.c) | 49 | ||||
-rw-r--r-- | server/server_game_process.h (renamed from server_game_process.h) | 11 |
24 files changed, 1218 insertions, 107 deletions
diff --git a/client/Makefile b/client/Makefile new file mode 100644 index 0000000..eeae6c6 --- /dev/null +++ b/client/Makefile @@ -0,0 +1,18 @@ +SRCMODULES = card_handling.c card_stack.c data_decryption.c\ + printing_game_frames.c verification_client_input.c client.c +OBJMODULES = $(SRCMODULES:.c=.o) +CC = gcc +CFLAGS = -Wall -g -c + +all: client + +%.o: %.с %.h + $(CC) $(CFLAGS) $< -o $@ + +client: $(OBJMODULES) + $(CC) $(LIBS) $^ -o $@ + +-include deps.mk + +deps.mk: $(SRCMODULES) + $(CC) -MM $^ > $@ diff --git a/client/card_handling.c b/client/card_handling.c new file mode 100644 index 0000000..011ad40 --- /dev/null +++ b/client/card_handling.c @@ -0,0 +1,64 @@ +#include "card_handling.h" + +#include <stdlib.h> +#include <string.h> + +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 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; +} + +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; +} diff --git a/client/card_handling.h b/client/card_handling.h new file mode 100644 index 0000000..8dcb072 --- /dev/null +++ b/client/card_handling.h @@ -0,0 +1,9 @@ +#ifndef CARD_HANDLING_H_SENTRY +#define CARD_HANDLING_H_SENTRY + +int convert_rank_to_int(const char *card); +int is_card_beaten(const char *attack_card, const char *defend_card, + const char *trump_suit); +int check_matched_ranks(const char *attack_card, const char *not_defender_card); + +#endif diff --git a/client/card_stack.c b/client/card_stack.c new file mode 100644 index 0000000..5d0700b --- /dev/null +++ b/client/card_stack.c @@ -0,0 +1,193 @@ +#include "card_stack.h" +#include "card_handling.h" +#include "client.h" + +#include <stdlib.h> +#include <string.h> + +void init_stack(player_cards *deck) +{ + *deck = NULL; +} + +void push_stack(player_cards *deck, char *str) +{ + struct card_stack_item *tmp = malloc(sizeof(struct card_stack_item)); + tmp->str = str; + tmp->tip = ' '; + tmp->is_usable = 0; + tmp->next = *deck; + *deck = tmp; +} + +void clear_stack(player_cards *deck) +{ + struct card_stack_item *tmp; + + while(*deck) { + tmp = *deck; + *deck = tmp->next; + if(tmp->str) + free(tmp->str); + free(tmp); + } +} + +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'; + + while(deck) { + deck->tip = letter; + ++letter; + if(letter > 'z') + letter = 'A'; + deck = 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; + + while(deck) { + /* is the card already marked? */ + if(deck->is_usable) { + deck = deck->next; + continue; + } + card = deck->str; + target_rank = convert_rank_to_int(card); + search_deck = deck->next; + while(search_deck) { + if(search_deck->is_usable) { + search_deck = search_deck->next; + continue; + } + found_card = search_deck->str; + found_rank = convert_rank_to_int(found_card); + if(found_rank == target_rank) + search_deck->is_usable = 1; + search_deck = search_deck->next; + } + deck = deck->next; + } +} +#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) +{ + int i; + + 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)) + { + deck->is_usable = 1; + break; + } + 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) +{ + int i; + + while(deck) { + for(i = 0; i <= cot->card_arr_idx; ++i) { + if(cot->card_arr[i][0] == '-' || cot->card_arr[i][0] == '\\') + continue; + if(check_matched_ranks(cot->card_arr[i], deck->str)) { + deck->is_usable = 1; + break; + } + } + deck = deck->next; + } +} + +int card_search_by_letter(player_cards deck, int letter) +{ + while(deck) { + if(deck->tip == letter && deck->is_usable) { + deck->is_usable = 0; + return 1; + } + deck = deck->next; + } + return 0; +} diff --git a/client/card_stack.h b/client/card_stack.h new file mode 100644 index 0000000..7cb5798 --- /dev/null +++ b/client/card_stack.h @@ -0,0 +1,29 @@ +#ifndef CARD_STACK_H_SENTRY +#define CARD_STACK_H_SENTRY + +struct card_stack_item { + char *str; + struct card_stack_item *next; + /* like a, b, c etc */ + unsigned char tip; + /* 1 - can be used, 0 - can't take it */ + int is_usable; +}; + +typedef struct card_stack_item* player_cards; + +void init_stack(player_cards *deck); +void push_stack(player_cards *deck, char *str); +void clear_stack(player_cards *deck); +int is_empty_stack(player_cards deck); +void add_hint_letters_stack(player_cards deck); +void mark_card_for_attackers_stack(player_cards deck); + +struct cards_on_table; +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); + +#endif diff --git a/client/client.c b/client/client.c new file mode 100644 index 0000000..d932a51 --- /dev/null +++ b/client/client.c @@ -0,0 +1,245 @@ +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +#include "client.h" +#include "data_decryption.h" +#include "printing_game_frames.h" +#include "verification_client_input.h" + +static const char *ip = "127.0.0.1"; +static const int port = 8082; + +static void get_data_from_server(struct client *cl, fd_set *readfds) +{ + 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); + decrypt_set_state(cl, &end_p); + update_info = 1; + cl->display_new_frame = 1; + } + if(update_info) { + switch(cl->state) { + case first_player: + break; + case confirmation_waiting: + 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_expectation: + decrypt_set_base_info(cl, end_p+1, &end_p); + decrypt_set_position_whose_turn(cl, end_p+1, &end_p); + break; + case defense_expectation: + decrypt_set_base_info(cl, end_p+1, &end_p); + decrypt_set_position_whose_turn(cl, end_p+1, &end_p); + decrypt_set_card_queue(cl, end_p+1); + break; + case card_acceptance_status: + decrypt_set_card_acceptance_status(cl, cl->buffer); + break; + /* no data to extract */ + case tossing_limit_status: + default: + {} + } + } +} + +static void prepare_tips_for_client(struct client *cl) +{ + char *trump_suit = NULL; + + if(!is_empty_stack(cl->deck)) + add_hint_letters_stack(cl->deck); + + switch(cl->state) { + case attack: + mark_card_for_attackers_stack(cl->deck); + break; + case defense: + trump_suit = cl->trump_card + strlen(cl->trump_card) - 1; + mark_card_for_defenders_stack(cl->deck, &cl->cot, trump_suit); + break; + case tossing: + mark_card_for_tossing_stack(cl->deck, &cl->cot); + break; + default: + {} + } +} + +static void change_client_frame(struct client *cl) +{ + if(cl->display_new_frame) { + switch(cl->state) { + case first_player: + pgf_first_player(); + break; + case confirmation_waiting: + pgf_confirmation_waiting(cl->total_players); + break; + case display_only_table: + case attack_expectation: + case defense_expectation: + case tossing_expectation: + pgf_table(cl); + if(cl->state == attack_expectation || + cl->state == defense_expectation || + cl->state == tossing_expectation) + { + pgf_select_idle_mode_message(cl->state); + } + break; + case attack: + case defense: + case tossing: + pgf_table(cl); + pgf_suggestions(cl); + break; + case card_acceptance_status: + pgf_card_acceptance_status(cl->all_input_cards_accepted); + break; + case tossing_limit_status: + pgf_tossing_limit_status(); + break; + default: + {} + } + cl->display_new_frame = 0; + } +} + +static void send_data_to_server(struct client *cl, fd_set *readfds) +{ + int input_result; + + if(FD_ISSET(0, readfds)) { /* 0 - stdin */ + read(0, cl->buffer, max_buffer_size); + switch(cl->state) { + case confirmation_waiting: + input_result = vci_confirmation_waiting(cl->fd, cl->buffer); + break; + case attack: + case tossing: + input_result = vci_attack_or_tossing(cl->fd, cl->buffer, cl->deck, + cl->state); + break; + case defense: + input_result = vci_defense(cl->fd, cl->buffer, cl->deck); + break; + default: + {} + } + /* if 0, then re-tracking the input client */ + if(input_result) + cl->pending_server_response = 1; + } +} + +static int check_tracking_client_input(enum client_states state, + int pending_server_response) +{ + if(pending_server_response) + return 0; + + switch(state) { + case confirmation_waiting: + case attack: + case defense: + case tossing: + return 1; + default: + return 0; + } + return 0; +} + +int main_loop(struct client *cl) +{ + int select_result; + fd_set readfds; + + for(;;) { + FD_ZERO(&readfds); + + FD_SET(cl->fd, &readfds); + 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; + get_data_from_server(cl, &readfds); + prepare_tips_for_client(cl); + if(cl->display_new_frame) + change_client_frame(cl); + send_data_to_server(cl, &readfds); + } +} + +static void init_client(struct client *cl) +{ + cl->fd = -1; + cl->state = none; + cl->total_players = 0; + 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; + cl->cq.card_arr_idx = -1; + cl->position_whose_turn = 0; + cl->display_new_frame = 0; + cl->all_input_cards_accepted = 0; +} + +/* + * 0 - failure + * 1 - success + */ +static int connect_to_server(struct client *cl) +{ + int connect_result; + struct sockaddr_in addr; + + cl->fd = socket(AF_INET, SOCK_STREAM, 0); + if(cl->fd == -1) + return 0; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(ip); + addr.sin_port = htons(port); + + connect_result = connect(cl->fd, (struct sockaddr*) &addr, sizeof(addr)); + if(connect_result == -1) + return 0; + return 1; +} + +int main() +{ + struct client cl; + + init_client(&cl); + if(!connect_to_server(&cl)) + return 1; + return main_loop(&cl); +} diff --git a/client/client.h b/client/client.h new file mode 100644 index 0000000..f73cdce --- /dev/null +++ b/client/client.h @@ -0,0 +1,71 @@ +#ifndef CLIENT_H_SENTRY +#define CLIENT_H_SENTRY + +#include "card_stack.h" + +enum { + max_buffer_size = 4096, + max_cot_arr_size = 18, + card_size = 4, + max_cq_arr_size = 5 +}; + +enum client_states { + none, + first_player, + confirmation_waiting, + /* in game */ + display_only_table, + attack_expectation, + defense_expectation, + tossing_expectation, + attack, + defense, + tossing, + card_acceptance_status, + tossing_limit_status +}; + +struct cards_on_table { + /* + * example: 2^ \ - 10# \ K# + * [2 ^ '\0' ][1 0 # '\0'][\ '\0' ] + */ + char card_arr[max_cot_arr_size][card_size]; + /* index of the last filled element */ + int card_arr_idx; +}; + +struct card_queue { + char card_arr[max_cq_arr_size][card_size]; + int card_arr_idx; +}; + +struct card_count { + int *number_arr; + /* + * will only store the initial number of players + * (idx: total_players - 1 + */ + int number_arr_idx; +}; + +struct client { + int fd; + enum client_states state; + char buffer[max_buffer_size]; + int total_players; + int total_cards_left; + int player_position; + char trump_card[4]; + struct card_count cc; + struct cards_on_table cot; + player_cards deck; + int pending_server_response; + struct card_queue cq; + int position_whose_turn; + int display_new_frame; + int all_input_cards_accepted; +}; + +#endif diff --git a/client/data_decryption.c b/client/data_decryption.c new file mode 100644 index 0000000..2d10561 --- /dev/null +++ b/client/data_decryption.c @@ -0,0 +1,169 @@ +#include "data_decryption.h" +#include "client.h" +#include "card_stack.h" + +#include <stdlib.h> +#include <string.h> + +void decrypt_set_state(struct client *cl, char **end_p) +{ + enum client_states found_state; + + found_state = (enum client_states) strtol(cl->buffer, end_p, 10); + cl->state = found_state; +} + +/* return convert number from str */ +int decrypt_get_number(char *start_p, char **end_p) +{ + return strtol(start_p, end_p, 10); +} + +static void decrypt_set_trump_card(struct client *cl, char *start_p, + char **end_p) +{ + int i; + + for(i = 0; *start_p != '\0'; ++start_p, ++i) + cl->trump_card[i] = *start_p; + cl->trump_card[i] = '\0'; + /* move to : */ + ++start_p; + *end_p = start_p; +} + +void decrypt_set_base_info(struct client *cl, char *start_p, char **end_p) +{ + int i, j; + char tmp_card[4]; + char *card = NULL; + + cl->total_players = decrypt_get_number(start_p, end_p); + cl->total_cards_left = decrypt_get_number(*end_p+1, end_p); + cl->player_position = decrypt_get_number(*end_p+1, end_p); + decrypt_set_trump_card(cl, *end_p+1, end_p); + + if(!cl->cc.number_arr) { + cl->cc.number_arr = malloc(cl->total_players * sizeof(int)); + /* + * memorize the size of the array, + * because later the number of players may change (client disconnection) + */ + cl->cc.number_arr_idx = cl->total_players-1; + } + + /* ============== extraction quantity of cards =============== */ + + /* numbers are separated by '\' */ + i = 0; + do { + cl->cc.number_arr[i] = decrypt_get_number(*end_p+1, end_p); + ++i; + } while(**end_p != ':'); + + /* ============== extraction cards on table =============== */ + i = 0, j = 0; + for(start_p = *end_p + 1; *start_p != ':'; ++start_p) { + /* empty table */ + if(*start_p == '0') { + /* to delimiter : */ + ++start_p; + i = -1; + break; + } + /* delimiter between cards on table */ + if(*start_p == '+') { + cl->cot.card_arr[i][j] = '\0'; + ++i; + j = 0; + continue; + } + cl->cot.card_arr[i][j] = *start_p; + ++j; + } + /* for the last card we need to add a null character */ + if(i != -1) + cl->cot.card_arr[i][j] = '\0'; + cl->cot.card_arr_idx = i; + + /* ================= extraction player's deck ================*/ + /* clear previous stack */ + if(cl->deck) + clear_stack(&cl->deck); + init_stack(&cl->deck); + + for(++start_p, i = 0; *start_p != ':' && *start_p != '\n'; ++start_p) { + /* empty deck */ + if(*start_p == '0') { + i = -1; + /* to delimiter ':' or '\n' */ + ++start_p; + break; + } + /* delimiter */ + if(*start_p == '\\') { + tmp_card[i] = '\0'; + card = malloc(strlen(tmp_card) + 1); + strcpy(card, tmp_card); + push_stack(&cl->deck, card); + i = 0; + } + tmp_card[i] = *start_p; + ++i; + } + if(i != -1) { + tmp_card[i] = '\0'; + card = malloc(strlen(tmp_card) + 1); + strcpy(card, tmp_card); + push_stack(&cl->deck, card); + } + *end_p = start_p; +} + +void decrypt_set_position_whose_turn(struct client *cl, char *start_p, + char **end_p) +{ + cl->position_whose_turn = decrypt_get_number(start_p, end_p); +} + +void decrypt_set_card_queue(struct client *cl, char *start_p) +{ + int i, j; + + for(i = 0, j = 0; *start_p != '\n'; ++start_p) { + /* empty queue */ + if(*start_p == '0') { + i = -1; + break; + } + /* delimiter '\' */ + if(*start_p == '\\') { + cl->cq.card_arr[i][j] = '\0'; + j = 0; + ++i; + continue; + } + cl->cq.card_arr[i][j] = *start_p; + ++j; + } + /* last element */ + if(i != -1) + cl->cq.card_arr[i][j] = '\0'; + cl->cq.card_arr_idx = i; +} + +void decrypt_set_card_acceptance_status(struct client *cl, char *start_p) +{ + int i; + char tmp_buffer[8]; + + for(i = 0; *start_p != '\n'; ++start_p, ++i) + tmp_buffer[i] = *start_p; + tmp_buffer[i] = '\0'; + if(!strcmp(tmp_buffer, "all")) { + cl->all_input_cards_accepted = 1; + return; + } + if(!strcmp(tmp_buffer, "not all")) + cl->all_input_cards_accepted = 0; +} diff --git a/client/data_decryption.h b/client/data_decryption.h new file mode 100644 index 0000000..b53e53f --- /dev/null +++ b/client/data_decryption.h @@ -0,0 +1,14 @@ +#ifndef DATA_DECRYPTION_H_SENTRY +#define DATA_DECRYPTION_H_SENTRY + +#include "client.h" + +void decrypt_set_state(struct client *cl, char **end_p); +int decrypt_get_number(char *start_p, char **end_p); +void decrypt_set_base_info(struct client *cl, char *start_p, char **end_p); +void decrypt_set_position_whose_turn(struct client *cl, char *start_p, + char **end_p); +void decrypt_set_card_queue(struct client *cl, char *start_p); +void decrypt_set_card_acceptance_status(struct client *cl, char *start_p); + +#endif diff --git a/client/printing_game_frames.c b/client/printing_game_frames.c new file mode 100644 index 0000000..38f1a78 --- /dev/null +++ b/client/printing_game_frames.c @@ -0,0 +1,104 @@ +#include "printing_game_frames.h" +#include "card_stack.h" + +#include <stdio.h> + +void pgf_first_player() +{ + printf("=======================================" + " You're the first player" + "Waiting for other players to connect..." + "=======================================\n"); +} + +void pgf_confirmation_waiting(int total_players) +{ + printf("=======================================" + " To start game press <Enter> key " + "Connected players: %u/8 " + "=======================================\n", total_players); +} + +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 ]", cl->trump_card, cl->total_cards_left); + printf("\n\n\n"); + /* ================= cards on table ================ */ + for(i = 0; i <= cl->cot.card_arr_idx; i += 3) + 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) + for(i = 0; i <= cl->cq.card_arr_idx; ++i) + printf(" %s \\ -\n", cl->cq.card_arr[i]); + printf("\n\n"); + /* ================ player's deck ================ */ + deck = cl->deck; + i = 0; + while(deck) { + printf("%c: %s ", deck->tip, deck->str); + ++i; + /* line break every 6 cards */ + if(!(i % 6)) + printf("\n"); + deck = deck->next; + } + printf("\n"); +} + +void pgf_suggestions(struct client *cl) +{ + struct card_stack_item *deck = NULL; + + if(cl->state == attack || cl->state == tossing) + printf("you can specify more than one card " + "(under certain conditions)\n"); + deck = cl->deck; + while(deck) { + if(deck->is_usable) + printf("%c", deck->tip); + deck = deck->next; + } + printf(" > "); +} + +void pgf_select_idle_mode_message(enum client_states state) +{ + switch(state) { + case attack_expectation: + printf("waiting for the attacker's turn\n"); + break; + case defense_expectation: + printf("waiting for the defender's turn\n"); + break; + case tossing_expectation: + printf("waiting for other players to toss cards\n"); + break; + default: + {} + } +} + +void pgf_card_acceptance_status(int all_input_cards_accepted) +{ + if(all_input_cards_accepted) + printf("all cards accepted\n"); + else + printf("not all cards were accepted\n"); +} + +void pgf_tossing_limit_status() +{ + printf("the cards were not accepted.\n" + "The other players have already tossed cards.\n"); +} diff --git a/client/printing_game_frames.h b/client/printing_game_frames.h new file mode 100644 index 0000000..e3c844a --- /dev/null +++ b/client/printing_game_frames.h @@ -0,0 +1,14 @@ +#ifndef PRINTING_GAME_FRAMES_H_SENTRY +#define PRINTING_GAME_FRAMES_H_SENTRY + +#include "client.h" + +void pgf_first_player(); +void pgf_confirmation_waiting(int total_players); +void pgf_table(struct client *cl); +void pgf_suggestions(struct client *cl); +void pgf_select_idle_mode_message(enum client_states state); +void pgf_card_acceptance_status(int all_input_cards_accepted); +void pgf_tossing_limit_status(); + +#endif diff --git a/client/verification_client_input.c b/client/verification_client_input.c new file mode 100644 index 0000000..2134f30 --- /dev/null +++ b/client/verification_client_input.c @@ -0,0 +1,46 @@ +#include "verification_client_input.h" + +#include <stdio.h> +#include <unistd.h> + +/* + * 1 - response received + * 0 - waiting for re-entry of data + */ +int vci_confirmation_waiting(int fd, char *buffer) +{ + if(buffer[0] == '\n') { + write(fd, buffer, 1); + return 1; + } + else + printf("please press enter\n"); + return 0; +} + +int vci_attack_or_tossing(int fd, char *buffer, player_cards deck, + enum client_states state) +{ + int i; + + if(state == tossing && buffer[0] == '\n') /* cancel card tossing */ + return 1; + + for(i = 0; buffer[i] != '\n'; ++i) + if(!card_search_by_letter(deck, buffer[i])) { + printf("incorrect input\n"); + return 0; + } + return 1; +} + +int vci_defense(int fd, char *buffer, player_cards deck) +{ + if(buffer[0] == '\n') /* the player does not want to keep the defense */ + return 1; + if(!card_search_by_letter(deck, buffer[0])) + return 0; + if(buffer[1] != '\n') + return 0; + return 1; +} diff --git a/client/verification_client_input.h b/client/verification_client_input.h new file mode 100644 index 0000000..690f36e --- /dev/null +++ b/client/verification_client_input.h @@ -0,0 +1,12 @@ +#ifndef VERIFICATION_CLIENT_INPUT_H_SENTRY +#define VERIFICATION_CLIENT_INPUT_H_SENTRY + +#include "card_stack.h" +#include "client.h" + +int vci_confirmation_waiting(int fd, char *buffer); +int vci_attack_or_tossing(int fd, char *buffer, player_cards deck, + enum client_states state); +int vci_defense(int fd, char *buffer, player_cards deck); + +#endif diff --git a/Makefile b/server/Makefile index 6fb2c5c..6fb2c5c 100644 --- a/Makefile +++ b/server/Makefile diff --git a/card_queue.c b/server/card_queue.c index 194ea0c..194ea0c 100644 --- a/card_queue.c +++ b/server/card_queue.c diff --git a/card_queue.h b/server/card_queue.h index 778ece4..778ece4 100644 --- a/card_queue.h +++ b/server/card_queue.h diff --git a/card_stack.c b/server/card_stack.c index aa8af71..aa8af71 100644 --- a/card_stack.c +++ b/server/card_stack.c diff --git a/card_stack.h b/server/card_stack.h index d380ded..d380ded 100644 --- a/card_stack.h +++ b/server/card_stack.h diff --git a/server.c b/server/server.c index 5153107..0a2bd0f 100644 --- a/server.c +++ b/server/server.c @@ -73,15 +73,20 @@ static void init_new_game(struct server *serv) lowest_trump = 0; serv->shuffled_deck = get_shuffled_deck(); + serv->trump_card = + extract_trump_card(serv->shuffled_deck, &serv->shuffled_deck_size); + serv->trump_suit = serv->trump_card + strlen(serv->trump_card) - 1; +#if 0 serv->trump_suit = find_trump_suit(serv->shuffled_deck, &serv->shuffled_deck_size); +#endif serv->turn_queue = malloc(sizeof(struct session*) * serv->connected_players_counter); - serv->card_quantity_arr = malloc(sizeof(int) * - serv->connected_players_counter); + /* number of cards each player holds */ + serv->cc.number_arr_idx = serv->connected_players_counter - 1; + serv->cc.number_arr = malloc(sizeof(int) * serv->connected_players_counter); serv->position_whose_turn = 0; - serv->cq = malloc(sizeof(struct card_queue)); - serv->cot = malloc(sizeof(struct cards_on_table)); + serv->cot.card_arr_idx = -1; /* * dealing cards to all and * determining who moves first @@ -111,13 +116,12 @@ static void init_new_game(struct server *serv) shift_turn_queue_by_one(serv->turn_queue, serv->connected_players_counter); update_card_quantity_arr(serv); - init_queue(serv->cq); - serv->cot->card_arr_idx = -1; + init_queue(&serv->cq); serv->gi = get_new_game_info(serv->connected_players_counter, - serv->card_quantity_arr, + serv->cc.number_arr, serv->shuffled_deck_size, - serv->trump_suit, serv->position_whose_turn, - serv->cq, serv->cot); + serv->trump_card, serv->position_whose_turn, + &serv->cq, &serv->cot); } static void set_whose_turn(struct server *serv, enum client_game_states state) @@ -169,7 +173,7 @@ static void set_state_for_client(struct server *serv, if(serv->turn_queue[i] && serv->turn_queue[i] != serv->turn_queue[1]) { if(check_player_can_toss_card(serv->turn_queue[i]->deck, - serv->cot)) + &serv->cot)) { serv->turn_queue[i]->tm = answer_wait; serv->turn_queue[i]->state = tossing; @@ -199,49 +203,61 @@ static void set_record_status_for_all(struct server *serv) static int print_table_condition(struct server *serv) { - return !check_defender_can_defend(serv->cq, serv->turn_queue[1]->deck, + return !check_defender_can_defend(&serv->cq, serv->turn_queue[1]->deck, serv->trump_suit) && !check_someone_can_toss_card(serv->turn_queue, serv->connected_players_counter, - serv->cq, serv->cot); + &serv->cq, &serv->cot); } static int defense_condition(struct server *serv) { - return check_defender_can_defend(serv->cq, serv->turn_queue[1]->deck, + return check_defender_can_defend(&serv->cq, serv->turn_queue[1]->deck, serv->trump_suit); } - +/* + * TODO refactoring + */ static void define_phase_after_attack(struct server *serv) { if(print_table_condition(serv)) { set_state_for_client(serv, display_only_table); - put_all_cards_from_queue_to_table(serv->cot, serv->cq); + put_all_cards_from_queue_to_table(&serv->cot, &serv->cq); serv->turn_queue[1]->defense_lost = 1; serv->state = table; } else if(defense_condition(serv)) { set_state_for_client(serv, defense); set_whose_turn(serv, defense); - put_one_card_from_queue_to_table(serv->cot, serv->cq); + put_one_card_from_queue_to_table(&serv->cot, &serv->cq); serv->state = defense_phase_out; } else { - set_state_for_client(serv, tossing); - set_whose_turn(serv, tossing); - put_all_cards_from_queue_to_table(serv->cot, serv->cq); serv->turn_queue[1]->defense_lost = 1; - serv->state = tossing_phase_out; + put_all_cards_from_queue_to_table(&serv->cot, &serv->cq); + if(is_receiving_cards_limit(&serv->cot, serv->turn_queue[1]->deck, + &serv->cq)) { + set_state_for_client(serv, display_only_table); + serv->state = table; + } else { + set_state_for_client(serv, tossing); + set_whose_turn(serv, tossing); + serv->state = tossing_phase_out; + } + } } static void define_phase_after_defense(struct server *serv) { /* card wasn't beated */ - if(serv->cot->card_arr[serv->cot->card_arr_idx][0] == '-') { + if(serv->cot.card_arr[serv->cot.card_arr_idx][0] == '-') { serv->turn_queue[1]->defense_lost = 1; - put_all_cards_from_queue_to_table(serv->cot, serv->cq); - if(check_someone_can_toss_card(serv->turn_queue, + put_all_cards_from_queue_to_table(&serv->cot, &serv->cq); + /* go to tossing cards */ + if(!is_receiving_cards_limit(&serv->cot, serv->turn_queue[1]->deck, + &serv->cq) && + check_someone_can_toss_card(serv->turn_queue, serv->connected_players_counter, - serv->cq, serv->cot)) + &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); set_whose_turn(serv, tossing); @@ -253,10 +269,13 @@ static void define_phase_after_defense(struct server *serv) } /* can defender continue defense? */ } else { - if(is_empty_queue(serv->cq)) { - if(check_someone_can_toss_card(serv->turn_queue, + /* the defender has beaten the attack or tossing phase completely */ + if(is_empty_queue(&serv->cq)) { + if(!is_receiving_cards_limit(&serv->cot, serv->turn_queue[0]->deck, + &serv->cq) && + check_someone_can_toss_card(serv->turn_queue, serv->connected_players_counter, - serv->cq, serv->cot)) + &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); set_whose_turn(serv, tossing); @@ -269,7 +288,7 @@ static void define_phase_after_defense(struct server *serv) } else { /* defender can defense */ if(defense_condition(serv)) { - put_one_card_from_queue_to_table(serv->cot, serv->cq); + put_one_card_from_queue_to_table(&serv->cot, &serv->cq); set_state_for_client(serv, defense); set_whose_turn(serv, defense); serv->state = defense_phase_out; @@ -278,16 +297,16 @@ static void define_phase_after_defense(struct server *serv) #if 0 } else { serv->turn_queue[1]->defense_lost = 1; - put_all_cards_from_queue_to_table(serv->cot, serv->cq); + put_all_cards_from_queue_to_table(&serv->cot, &serv->cq); if(check_someone_can_toss_card(serv->turn_queue, serv->connected_players_counter, - serv->cq, serv->cot)) + &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); set_whose_turn(serv, tossing); serv->state = tossing_phase_out; } else { - move_all_cards_to_defender(serv->cot, + move_all_cards_to_defender(&serv->cot, &serv->turn_queue[1]->deck); /* add shifting of turn arr*/ set_state_for_client(serv, attack); @@ -303,16 +322,18 @@ static void define_phase_after_defense(struct server *serv) static void define_phase_after_tossing(struct server *serv) { if(serv->turn_queue[1]->defense_lost) { - if(is_empty_queue(serv->cq)) { + if(is_empty_queue(&serv->cq)) { /* nobody's put any cards on the table */ set_state_for_client(serv, display_only_table); serv->state = table; } else { - put_all_cards_from_queue_to_table(serv->cot, serv->cq); - if(check_someone_can_toss_card(serv->turn_queue, + put_all_cards_from_queue_to_table(&serv->cot, &serv->cq); + if(is_receiving_cards_limit(&serv->cot, serv->turn_queue[1]->deck, + &serv->cq) && + check_someone_can_toss_card(serv->turn_queue, serv->connected_players_counter, - serv->cq, serv->cot)) + &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); set_whose_turn(serv, tossing); @@ -324,22 +345,25 @@ static void define_phase_after_tossing(struct server *serv) } /* defense continue? */ } else { - if(is_empty_queue(serv->cq)) { + if(is_empty_queue(&serv->cq)) { set_state_for_client(serv, display_only_table); serv->state = table; } else { - if(check_defender_can_defend(serv->cq, serv->turn_queue[1]->deck, + if(check_defender_can_defend(&serv->cq, serv->turn_queue[1]->deck, serv->trump_suit)) { - put_one_card_from_queue_to_table(serv->cot, serv->cq); + put_one_card_from_queue_to_table(&serv->cot, &serv->cq); set_state_for_client(serv, defense); set_whose_turn(serv, defense); serv->state = defense_phase_out; } else { serv->turn_queue[1]->defense_lost = 1; - put_all_cards_from_queue_to_table(serv->cot, serv->cq); - if(check_someone_can_toss_card(serv->turn_queue, + put_all_cards_from_queue_to_table(&serv->cot, &serv->cq); + if(is_receiving_cards_limit(&serv->cot, + serv->turn_queue[1]->deck, + &serv->cq) && + check_someone_can_toss_card(serv->turn_queue, serv->connected_players_counter, - serv->cq, serv->cot)) + &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); set_whose_turn(serv, tossing); @@ -394,12 +418,12 @@ static void determine_server_state(struct server *serv) break; case table: if(serv->turn_queue[1]->defense_lost) { - move_all_cards_to_defender(serv->cot, &serv->turn_queue[1]->deck); + 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); } else { - remove_cards_from_table(serv->cot); + remove_cards_from_table(&serv->cot); shift_turn_queue_by_one(serv->turn_queue, serv->connected_players_counter); } @@ -409,7 +433,7 @@ static void determine_server_state(struct server *serv) update_card_quantity_arr(serv); deal_cards(serv->shuffled_deck, &serv->shuffled_deck_size, serv->turn_queue, serv->connected_players_counter, - serv->card_quantity_arr); + serv->cc.number_arr); serv->state = attack_phase_out; break; case defense_phase_out: @@ -566,11 +590,13 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, break; case attack_phase_in: if(FD_ISSET(i, readfds)) - result = get_cards_from_attacker(serv->sess_arr[i], serv->cq); + result = get_cards_from_attacker(serv->sess_arr[i], &serv->cot, + serv->turn_queue[1]->deck, + &serv->cq); break; case defense_phase_in: if(FD_ISSET(i, readfds)) - result = get_card_from_defender(serv->sess_arr[i], serv->cot, + result = get_card_from_defender(serv->sess_arr[i], &serv->cot, serv->trump_suit); break; case tossing_phase_in: @@ -581,7 +607,7 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, result = get_cards_from_tossing_player(serv->sess_arr[i], serv->turn_queue[1]->deck, - serv->cot, serv->cq); + &serv->cot, &serv->cq); if(result == 1 || result == 2) serv->sess_arr[i]->tm = answer_got; @@ -606,7 +632,7 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, int main_loop(struct server *serv) { - int maxfd, accept_result; + int maxfd, accept_result, select_result; fd_set readfds, writefds; for(;;) { @@ -622,7 +648,9 @@ int main_loop(struct server *serv) set_up_player_tracking(serv, &readfds, &writefds); - select(maxfd + 1, &readfds, &writefds, NULL, NULL); + select_result = select(maxfd + 1, &readfds, &writefds, NULL, NULL); + if(select_result == -1) + return 3; if(FD_ISSET(serv->listen_socket, &readfds)) { accept_result = accept_new_player(serv); @@ -669,9 +697,7 @@ static int init_server(struct server *serv, int port) serv->shuffled_deck = NULL; serv->shuffled_deck_size = max_shuffled_deck_size; serv->gi = NULL; - serv->card_quantity_arr = NULL; - serv->cq = NULL; - serv->cot = NULL; + serv->cc.number_arr = NULL; listen(serv->listen_socket, listen_qlen); return 1; diff --git a/server.h b/server/server.h index a97109f..46c965b 100644 --- a/server.h +++ b/server/server.h @@ -30,13 +30,16 @@ enum server_states { }; enum client_game_states { - display_only_table, + /* in game */ + display_only_table = 3, attack_expectation, defense_expectation, tossing_expectation, attack, defense, - tossing + tossing, + card_acceptance_status, + tossing_limit_status }; enum tossing_mode { @@ -67,6 +70,12 @@ struct cards_on_table { int card_arr_idx; }; +struct card_count { + int *number_arr; + /* will only store the initial number of players (idx) */ + int number_arr_idx; +}; + struct server { int change_server_state; enum server_states state; @@ -74,15 +83,17 @@ struct server { struct session **sess_arr; int max_sess_arr_size; int connected_players_counter; + /* TODO: make static allocation memory */ const char **shuffled_deck; int shuffled_deck_size; const char *trump_suit; + const char *trump_card; struct game_info *gi; struct session **turn_queue; - int *card_quantity_arr; + struct card_count cc; int position_whose_turn; - struct card_queue *cq; - struct cards_on_table *cot; + struct card_queue cq; + struct cards_on_table cot; }; #endif diff --git a/server_data_processing.c b/server/server_data_processing.c index 5c78f78..30953bf 100644 --- a/server_data_processing.c +++ b/server/server_data_processing.c @@ -31,14 +31,17 @@ static int read_from_client(int fd, char *buffer, int max_buffer_size) int print_message_for_first_player(int fd) { - stpcpy(output_buffer, "first\n"); - return write_to_client(fd, strlen("first\n")); + int data_size; + + data_size = sprintf(output_buffer, "%u\n", first_player); + return write_to_client(fd, data_size); } int print_connected_players(int fd, int number) { int data_size; - data_size = sprintf(output_buffer, "%u\n", number); + + data_size = sprintf(output_buffer, "%u:%u\n", confirmation_waiting, number); return write_to_client(fd, data_size); } @@ -58,7 +61,10 @@ int check_readiness(struct session *client) else return -1; } - +/* + * example: 10#\A^\7v'\n' + * or 0'\n' + */ static void copy_card_queue(int *offset, struct card_queue *cq) { int length, i; @@ -69,12 +75,17 @@ static void copy_card_queue(int *offset, struct card_queue *cq) length = strlen(next_attack_card->str); for(i = 0; i < length; ++i, ++*offset) *(output_buffer + *offset) = (next_attack_card->str)[i]; + /* delimiter */ *(output_buffer + *offset) = '\\'; ++*offset; } *(output_buffer + *offset-1) = ':'; } +/* + * example: 10#+\+Q#+A^+\+-+7v: + * or 0: + */ static void copy_cards_on_table(int *offset, struct cards_on_table cot) { int i, j, length; @@ -82,15 +93,18 @@ static void copy_cards_on_table(int *offset, struct cards_on_table cot) length = strlen(cot.card_arr[i]); for(j = 0; j < length; ++j, ++*offset) *(output_buffer + *offset) = cot.card_arr[i][j]; -#if 0 - *(output_buffer + *offset) = '\\'; -#endif + /* delimiter */ + *(output_buffer + *offset) = '+'; + ++*offset; } - *(output_buffer + *offset) = ':'; - /* free pos */ - ++*offset; + *(output_buffer + *offset-1) = ':'; } - +/* + * example: 10#\A^\7v: + * or 10#\A^\7v'\n' + * or 0: + * or 0'\n' + */ static void copy_own_deck(int *offset, player_cards deck) { const char *card; @@ -102,10 +116,10 @@ static void copy_own_deck(int *offset, player_cards deck) for(i = 0; i < length; ++i, ++*offset) *(output_buffer + *offset) = card[i]; *(output_buffer + *offset) = '\\'; + ++*offset; deck = deck->next; } - *(output_buffer + *offset) = ':'; - ++*offset; + *(output_buffer + *offset-1) = ':'; } static void copy_base_info(int *free_pos, struct game_info *gi, @@ -116,17 +130,27 @@ static void copy_base_info(int *free_pos, struct game_info *gi, *free_pos = sprintf(output_buffer, "%u:%u:%u:%u:%s:", state, gi->players_number, - gi->shuffled_cards_left, player_position, gi->trump_suit); - /* opponent's card count */ + gi->shuffled_cards_left, player_position, gi->trump_card); + /* + * opponent's card count + * example: 2\6\3: + */ for(i = 0; i < gi->players_number; ++i) { - *free_pos += sprintf(output_buffer + *free_pos, "%u:", + *free_pos += sprintf(output_buffer + *free_pos, "%u\\", gi->card_quantity_arr[i]); } + *(output_buffer + *free_pos-1) = ':'; + if(gi->cot->card_arr_idx != -1) copy_cards_on_table(free_pos, *gi->cot); + else + *free_pos += sprintf(output_buffer + *free_pos, "0:"); + if(!is_empty_stack(deck)) copy_own_deck(free_pos, deck); + else + *free_pos += sprintf(output_buffer + *free_pos, "0:"); } int print_game_part(const struct session *client, struct game_info *gi) @@ -157,17 +181,40 @@ int print_game_part(const struct session *client, struct game_info *gi) *(output_buffer + free_pos-1) = '\n'; break; case defense_expectation: + /* copying whose turn */ free_pos += sprintf(output_buffer + free_pos, "%u:", gi->position_whose_turn); - copy_card_queue(&free_pos, gi->cq); + /* copying card queue */ + if(is_empty_queue(gi->cq)) + free_pos += sprintf(output_buffer + free_pos, "0:"); + else + copy_card_queue(&free_pos, gi->cq); *(output_buffer + free_pos-1) = '\n'; + default: + {} } return write_to_client(client->fd, free_pos); } +#if 0 +static int is_receiving_cards_limit(int total_defense_cards, int total_attack_cards) +{ + 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; +} +#endif -int get_cards_from_attacker(struct session *client, struct card_queue *cq) +int get_cards_from_attacker(struct session *client, + const struct cards_on_table *cot, + const player_cards defense_deck, + struct card_queue *cq) { int read_result, i, j; + int card_return_status = 0, all_cards_received_status = 1; + int data_length; char given_card[4]; const char *stack_card = NULL; @@ -178,13 +225,22 @@ int get_cards_from_attacker(struct session *client, struct card_queue *cq) if(client->buffer[i] == '\\') { given_card[j] = '\0'; j = 0; + if(card_return_status) { + all_cards_received_status = 0; + break; + } stack_card = remove_card_from_stack(&client->deck, given_card); push_queue(cq, stack_card); + if(is_receiving_cards_limit(cot, defense_deck, cq)) + card_return_status = 1; continue; } given_card[j] = client->buffer[i]; ++j; } + data_length = sprintf(output_buffer, "%d:%s\n", card_acceptance_status, + all_cards_received_status ? "all" : "not all"); + write_to_client(client->fd, data_length); return read_result; } @@ -217,28 +273,20 @@ int get_card_from_defender(struct session *client, struct cards_on_table *cot, return 0; } -static int skip_cards_in_queue(int total_defense_cards, int total_attack_cards) -{ - 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; -} - /* * 0 - buffer overflow or client closed connection * 1 - some number of cards added to card queue * 2 - card toss limit was reached when accepting cards from this player * 3 - player refused to toss the card + * + * example: 10#\A^\7v\'\n' */ int get_cards_from_tossing_player(struct session *client, const player_cards defense_deck, struct cards_on_table *cot, struct card_queue *cq) { - int read_result, i, j, total_attack_cards, total_defense_cards; + int read_result, i, j; int card_return_status = 0, all_cards_received_status = 1; int data_length; char given_card[4]; @@ -248,10 +296,6 @@ int get_cards_from_tossing_player(struct session *client, if(!read_result) return read_result; - 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); - for(i = 0, j = 0; i < read_result; ++i) { if(client->buffer[i] == '\\') { /* cancellation */ @@ -259,9 +303,9 @@ int get_cards_from_tossing_player(struct session *client, return 3; /* tossing limit was set */ if(client->tm == cancel) { - /* 8 - it's impossible to accept cards due to tossing limit */ - data_length = sprintf(output_buffer, "%d:%s\n", 8, - "tossing limit"); + /* it's impossible to accept cards due to tossing limit */ + data_length = + sprintf(output_buffer, "%d\n", tossing_limit_status); write_to_client(client->fd, data_length); return 3; } @@ -272,8 +316,7 @@ int get_cards_from_tossing_player(struct session *client, } else if(is_correct_tossing_card(given_card, cot)) { stack_card = remove_card_from_stack(&client->deck, given_card); push_queue(cq, stack_card); - total_attack_cards += find_out_card_quantity_in_cq(cq); - if(skip_cards_in_queue(total_defense_cards, total_attack_cards)) + if(is_receiving_cards_limit(cot, defense_deck, cq)) { card_return_status = 1; } @@ -284,7 +327,7 @@ int get_cards_from_tossing_player(struct session *client, ++j; } /* 7 -- state for result of received cards */ - data_length = sprintf(output_buffer, "%d:%s\n", 7, + data_length = sprintf(output_buffer, "%d:%s\n", card_acceptance_status, all_cards_received_status ? "all" : "not all"); write_to_client(client->fd, data_length); if(all_cards_received_status) diff --git a/server_data_processing.h b/server/server_data_processing.h index 9ebe5ad..875fd98 100644 --- a/server_data_processing.h +++ b/server/server_data_processing.h @@ -7,7 +7,10 @@ int print_message_for_first_player(int fd); int print_connected_players(int fd, int number); int check_readiness(struct session *client); int print_game_part(const struct session *client, struct game_info *gi); -int get_cards_from_attacker(struct session *client, struct card_queue *cq); +int get_cards_from_attacker(struct session *client, + const struct cards_on_table *cot, + const player_cards defense_deck, + struct card_queue *cq); int get_card_from_defender(struct session *client, struct cards_on_table *cot, const char *trump_suit); int get_cards_from_tossing_player(struct session *client, diff --git a/server_game_process.c b/server/server_game_process.c index 99b50fe..8bf4e60 100644 --- a/server_game_process.c +++ b/server/server_game_process.c @@ -77,16 +77,30 @@ void deal_cards(const char **shuffled_deck, int *shuffled_cards_left, } } +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) + if(trump_suit) { shuffled_deck[0] = NULL; - trump_suit += strlen(trump_suit) - 1; - --*cards_left; + trump_suit += strlen(trump_suit) - 1; + --*cards_left; + } return trump_suit; } +#endif int convert_rank_to_int(const char *card) { @@ -158,14 +172,14 @@ void update_card_quantity_arr(struct server *serv) 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->card_quantity_arr[player_position_idx] = + 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_suit, + const char *trump_card, int position_whose_turn, struct card_queue *cq, struct cards_on_table *cot) @@ -175,7 +189,7 @@ struct game_info* get_new_game_info(int players_number, int *card_quantity_arr, gi->players_number = players_number; gi->card_quantity_arr = card_quantity_arr; gi->shuffled_cards_left = shuffled_cards_left; - gi->trump_suit = trump_suit; + gi->trump_card = trump_card; gi->position_whose_turn = position_whose_turn; gi->cq = cq; gi->cot = cot; @@ -308,7 +322,7 @@ int check_someone_can_toss_card(struct session **turn_queue, } 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; @@ -438,3 +452,24 @@ int check_all_answers_were_received(const struct session **turn_queue, int size) 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; +} diff --git a/server_game_process.h b/server/server_game_process.h index 5cddc27..8891a56 100644 --- a/server_game_process.h +++ b/server/server_game_process.h @@ -13,7 +13,7 @@ struct game_info { int players_number; int *card_quantity_arr; int shuffled_cards_left; - const char* trump_suit; + const char* trump_card; int position_whose_turn; struct cards_on_table *cot; struct card_queue *cq; @@ -25,7 +25,10 @@ void deal_first_cards(const char **shuffled_deck, int *cards_left, void deal_cards(const char **shuffled_deck, int *shuffled_cards_left, struct session **turn_queue, int players_number, int *card_quantity_arr); +const char* extract_trump_card(const char **shuffled_deck, int *cards_left); +#if 0 const char* find_trump_suit(const char **shuffled_deck, int *cards_left); +#endif int find_lowest_trump(player_cards deck, const char *trump); void shift_turn_queue_by_one(struct session **turn_queue, int size); void move_turn_queue_two_players_ahead(struct session **turn_queue, int size); @@ -33,7 +36,7 @@ void update_card_quantity_arr(struct server *serv); struct game_info* get_new_game_info(int players_number, int *card_quantity_arr, int shuffled_cards_left, - const char *trump_suit, + const char *trump_card, int position_whose_turn, struct card_queue *cq, struct cards_on_table *cot); @@ -69,5 +72,7 @@ int calculate_defense_card_quantity_on_table(const struct cards_on_table *cot); int calculate_attack_card_quantity_on_table(const struct cards_on_table *cot); int check_all_answers_were_received(const struct session **turn_queue, int size); - +int is_receiving_cards_limit(const struct cards_on_table *cot, + player_cards defense_deck, + const struct card_queue *cq); #endif |