back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
path: root/server/server_data_processing.c
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 /server/server_data_processing.c
parent9e9919b897b00ff23aee6581471b4d7b4567bf4a (diff)
downloaddurak-a2d696dea797faaa3157046c8ae89cd70e965bff.tar.gz
durak-a2d696dea797faaa3157046c8ae89cd70e965bff.tar.bz2
durak-a2d696dea797faaa3157046c8ae89cd70e965bff.zip
Prefinal version
Added client. Moved files to directories.
Diffstat (limited to 'server/server_data_processing.c')
-rw-r--r--server/server_data_processing.c337
1 files changed, 337 insertions, 0 deletions
diff --git a/server/server_data_processing.c b/server/server_data_processing.c
new file mode 100644
index 0000000..30953bf
--- /dev/null
+++ b/server/server_data_processing.c
@@ -0,0 +1,337 @@
+#include "server_data_processing.h"
+#include "server.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+
+enum {
+ output_buffer_size = 1024
+};
+
+static char output_buffer[output_buffer_size];
+
+static int write_to_client(int fd, int length)
+{
+ return write(fd, output_buffer, length);
+}
+
+static int read_from_client(int fd, char *buffer, int max_buffer_size)
+{
+ int read_result;
+ read_result = read(fd, buffer, max_buffer_size);
+ if(read_result <= 0)
+ return 0;
+ /* buffer overflow */
+ if(read_result >= max_buffer_size)
+ return 0;
+ return read_result;
+}
+
+int print_message_for_first_player(int fd)
+{
+ 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:%u\n", confirmation_waiting, number);
+ return write_to_client(fd, data_size);
+}
+
+/*
+ * 1 - ready
+ * 0 - buffer overflow or player closed session
+ * -1 - not ready
+ */
+int check_readiness(struct session *client)
+{
+ int read_result;
+ read_result = read_from_client(client->fd, client->buffer, max_buffer_size);
+ if(!read_result)
+ return read_result;
+ if(client->buffer[0] == '\n')
+ return 1;
+ 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;
+ struct card_queue_item *next_attack_card;
+
+ next_attack_card = NULL;
+ while((next_attack_card = get_next_card_from_queue(cq, next_attack_card))) {
+ 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;
+ for(i = 0; i <= cot.card_arr_idx; ++i) {
+ length = strlen(cot.card_arr[i]);
+ for(j = 0; j < length; ++j, ++*offset)
+ *(output_buffer + *offset) = cot.card_arr[i][j];
+ /* delimiter */
+ *(output_buffer + *offset) = '+';
+ ++*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;
+ int length, i;
+
+ while(deck) {
+ card = deck->str;
+ length = strlen(card);
+ for(i = 0; i < length; ++i, ++*offset)
+ *(output_buffer + *offset) = card[i];
+ *(output_buffer + *offset) = '\\';
+ ++*offset;
+ deck = deck->next;
+ }
+ *(output_buffer + *offset-1) = ':';
+}
+
+static void copy_base_info(int *free_pos, struct game_info *gi,
+ enum client_game_states state, player_cards deck,
+ int player_position)
+{
+ int i;
+
+ *free_pos =
+ sprintf(output_buffer, "%u:%u:%u:%u:%s:", state, gi->players_number,
+ 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\\",
+ 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)
+{
+ int free_pos; /* free_pos == data length */
+
+ copy_base_info(&free_pos, gi, client->state, client->deck,
+ client->player_position);
+
+ switch(client->state) {
+ case display_only_table:
+ /* let the client print card tips and wait for input */
+ case attack:
+ case defense:
+ /*
+ * who haven't got tossing card (including defender) must wait
+ * when other players make moves
+ */
+ case tossing_expectation:
+ case tossing:
+ /* instead of last ':' */
+ *(output_buffer + free_pos-1) = '\n';
+ break;
+ /* other clents will be waiting particular player */
+ case attack_expectation:
+ free_pos += sprintf(output_buffer + free_pos, "%u:",
+ gi->position_whose_turn);
+ *(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);
+ /* 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,
+ 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;
+
+ read_result = read_from_client(client->fd, client->buffer, max_buffer_size);
+ if(!read_result)
+ return read_result;
+ for(i = 0, j = 0; i < read_result && client->buffer[i] != '\n'; ++i) {
+ 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;
+}
+
+/*
+ * 0 - error
+ * 1 - card was bited, not bited, or
+ * defender didn't want to continue defense phase
+ *
+ */
+int get_card_from_defender(struct session *client, struct cards_on_table *cot,
+ const char * trump_suit)
+{
+ int read_result, i;
+ char given_card[4];
+ const char *stack_card = NULL;
+
+ read_result = read_from_client(client->fd, client->buffer, max_buffer_size);
+ if(!read_result)
+ return read_result;
+ 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);
+ put_defender_card_on_table(cot, stack_card);
+ return 1;
+ } else
+ 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;
+ int card_return_status = 0, all_cards_received_status = 1;
+ int data_length;
+ char given_card[4];
+ const char *stack_card = NULL;
+
+ read_result = read_from_client(client->fd, client->buffer, max_buffer_size);
+ 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 */
+ data_length =
+ sprintf(output_buffer, "%d\n", tossing_limit_status);
+ write_to_client(client->fd, data_length);
+ return 3;
+ }
+ given_card[j] = '\0';
+ j = 0;
+ if(card_return_status) {
+ all_cards_received_status = 0;
+ } else if(is_correct_tossing_card(given_card, cot)) {
+ 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;
+ }
+ /* 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");
+ write_to_client(client->fd, data_length);
+ if(all_cards_received_status)
+ return 1;
+ else
+ return 2;
+}