back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorscratko <m@scratko.xyz>2024-08-10 02:46:56 +0300
committerscratko <m@scratko.xyz>2024-08-10 02:46:56 +0300
commita2d696dea797faaa3157046c8ae89cd70e965bff (patch)
tree74051e828ec401f399b2316a535c200f3afa95c5 /client
parent9e9919b897b00ff23aee6581471b4d7b4567bf4a (diff)
downloaddurak-a2d696dea797faaa3157046c8ae89cd70e965bff.tar.gz
durak-a2d696dea797faaa3157046c8ae89cd70e965bff.tar.bz2
durak-a2d696dea797faaa3157046c8ae89cd70e965bff.zip
Prefinal version
Added client. Moved files to directories.
Diffstat (limited to 'client')
-rw-r--r--client/Makefile18
-rw-r--r--client/card_handling.c64
-rw-r--r--client/card_handling.h9
-rw-r--r--client/card_stack.c193
-rw-r--r--client/card_stack.h29
-rw-r--r--client/client.c245
-rw-r--r--client/client.h71
-rw-r--r--client/data_decryption.c169
-rw-r--r--client/data_decryption.h14
-rw-r--r--client/printing_game_frames.c104
-rw-r--r--client/printing_game_frames.h14
-rw-r--r--client/verification_client_input.c46
-rw-r--r--client/verification_client_input.h12
13 files changed, 988 insertions, 0 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