#include "server_data_processing.h" #include "server.h" #include #include #include #include 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: 10#\A^\7v: * or: ='\n' * or: =: */ 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 =: */ 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 =: * or ='\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, "=:"); if(!is_empty_stack(deck)) copy_own_deck(free_pos, deck); else *free_pos += sprintf(output_buffer + *free_pos, "=:"); } int print_game_part(const struct session *client, enum server_states ss, struct game_info *gi) { enum spectator_mode sp_mode; 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: case spectator: /* 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, "=:"); else copy_card_queue(&free_pos, gi->cq); if(client->state == spectator) { if(ss == attack_phase_out) sp_mode = spectator_attack; else if(ss == defense_phase_out) sp_mode = spectator_defense; else if(ss == tossing_phase_out) sp_mode = spectator_tossing; else sp_mode = spectator_table; free_pos += sprintf(output_buffer + free_pos, "%u:", sp_mode); } *(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 /* * example: 7v\2#\A^\'\n' */ 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); 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] == '\\') { 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 * * example: 5v'\n' * or: '\n' */ 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); 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]; 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' * or: '\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); printf("%d\n", read_result); for(i = 0; i < read_result; ++i) putchar(client->buffer[i]); putchar('\n'); if(!read_result) return read_result; /* cancellation */ if(client->buffer[0] == '\n') return 3; for(i = 0, j = 0; i < read_result; ++i) { if(client->buffer[i] == '\\') { /* 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; } void print_game_result(const struct session *client, int durak_position) { int data_size; data_size = sprintf(output_buffer, "%u:%u\n", client->state, durak_position); write_to_client(client->fd, data_size); }