diff options
-rw-r--r-- | client/client.c | 20 | ||||
-rw-r--r-- | client/client.h | 13 | ||||
-rw-r--r-- | client/data_decryption.c | 16 | ||||
-rw-r--r-- | client/data_decryption.h | 4 | ||||
-rw-r--r-- | client/printing_game_frames.c | 32 | ||||
-rw-r--r-- | client/printing_game_frames.h | 3 | ||||
-rw-r--r-- | server/server.c | 219 | ||||
-rw-r--r-- | server/server.h | 20 | ||||
-rw-r--r-- | server/server_data_processing.c | 42 | ||||
-rw-r--r-- | server/server_data_processing.h | 5 | ||||
-rw-r--r-- | server/server_game_process.c | 101 | ||||
-rw-r--r-- | server/server_game_process.h | 22 |
12 files changed, 404 insertions, 93 deletions
diff --git a/client/client.c b/client/client.c index 4abcf7d..a5b3daf 100644 --- a/client/client.c +++ b/client/client.c @@ -54,13 +54,19 @@ static void get_data_from_server(struct client *cl, fd_set *readfds) decrypt_set_position_whose_turn(cl, end_p+1, &end_p); break; case defense_expectation: + case spectator: 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); + decrypt_set_card_queue(cl, end_p+1, &end_p); + if(cl->state == spectator) + decrypt_set_spectator_mode(cl, end_p+1); break; case card_acceptance_status: decrypt_set_card_acceptance_status(cl, end_p+1); break; + case result: + decrypt_set_durak_position(cl, end_p+1); + break; /* no data to extract */ case tossing_limit_status: default: @@ -102,6 +108,7 @@ static void prepare_tips_for_client(struct client *cl) static void change_client_frame(struct client *cl) { if(cl->display_new_frame) { + pgf_new_frame(); switch(cl->state) { case first_player: pgf_first_player(); @@ -121,6 +128,10 @@ static void change_client_frame(struct client *cl) pgf_select_idle_mode_message(cl->state); } break; + case spectator: + pgf_table(cl); + pgf_spectator_mode(cl->sp_mode); + break; case attack: case defense: case tossing: @@ -133,7 +144,10 @@ static void change_client_frame(struct client *cl) case tossing_limit_status: pgf_tossing_limit_status(); break; - default: + case result: + pgf_game_result(cl->durak_position); + break; + case none: {} } cl->display_new_frame = 0; @@ -229,6 +243,8 @@ static void init_client(struct client *cl) cl->display_new_frame = 0; cl->all_input_cards_accepted = 0; cl->data_left_in_buffer = 0; + cl->sp_mode = spectator_table; + cl->durak_position = 0; } /* diff --git a/client/client.h b/client/client.h index 9bdd8cc..1ff8f82 100644 --- a/client/client.h +++ b/client/client.h @@ -23,7 +23,16 @@ enum client_states { defense, tossing, card_acceptance_status, - tossing_limit_status + tossing_limit_status, + spectator, + result +}; + +enum spectator_mode { + spectator_attack, + spectator_defense, + spectator_tossing, + spectator_table }; struct cards_on_table { @@ -67,6 +76,8 @@ struct client { int display_new_frame; int all_input_cards_accepted; int data_left_in_buffer; + enum spectator_mode sp_mode; + int durak_position; }; #endif diff --git a/client/data_decryption.c b/client/data_decryption.c index b445454..1054c45 100644 --- a/client/data_decryption.c +++ b/client/data_decryption.c @@ -126,14 +126,15 @@ void decrypt_set_position_whose_turn(struct client *cl, char *start_p, cl->position_whose_turn = decrypt_get_number(start_p, end_p); } -void decrypt_set_card_queue(struct client *cl, char *start_p) +void decrypt_set_card_queue(struct client *cl, char *start_p, char **end_p) { int i, j; - for(i = 0, j = 0; *start_p != '\n'; ++start_p) { + for(i = 0, j = 0; *start_p != ':' && *start_p != '\n'; ++start_p) { /* empty queue */ if(*start_p == '=') { i = -1; + ++start_p; break; } /* delimiter '\' */ @@ -150,6 +151,7 @@ void decrypt_set_card_queue(struct client *cl, char *start_p) if(i != -1) cl->cq.card_arr[i][j] = '\0'; cl->cq.card_arr_idx = i; + *end_p = start_p; } void decrypt_set_card_acceptance_status(struct client *cl, char *start_p) @@ -167,3 +169,13 @@ void decrypt_set_card_acceptance_status(struct client *cl, char *start_p) if(!strcmp(tmp_buffer, "not all")) cl->all_input_cards_accepted = 0; } + +void decrypt_set_spectator_mode(struct client *cl, char *start_p) +{ + cl->sp_mode = (enum spectator_mode) decrypt_get_number(start_p, NULL); +} + +void decrypt_set_durak_position(struct client *cl, char *start_p) +{ + cl->durak_position = decrypt_get_number(start_p, NULL); +} diff --git a/client/data_decryption.h b/client/data_decryption.h index b53e53f..08772fe 100644 --- a/client/data_decryption.h +++ b/client/data_decryption.h @@ -8,7 +8,9 @@ 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_queue(struct client *cl, char *start_p, char **end_p); void decrypt_set_card_acceptance_status(struct client *cl, char *start_p); +void decrypt_set_spectator_mode(struct client *cl, char *start_p); +void decrypt_set_durak_position(struct client *cl, char *start_p); #endif diff --git a/client/printing_game_frames.c b/client/printing_game_frames.c index f75cec5..5c7deac 100644 --- a/client/printing_game_frames.c +++ b/client/printing_game_frames.c @@ -3,6 +3,14 @@ #include <stdio.h> +void pgf_new_frame() +{ + int i; + + for(i = 0; i < 25; ++i) + printf("\n"); +} + void pgf_first_player() { printf("=======================================\n" @@ -54,7 +62,8 @@ void pgf_table(struct client *cl) printf("\n"); deck = deck->next; } - printf("\n"); + if(cl->deck) + printf("\n"); } void pgf_suggestions(struct client *cl) @@ -104,3 +113,24 @@ void pgf_tossing_limit_status() printf("the cards were not accepted.\n" "The other players have already tossed cards.\n"); } + +void pgf_spectator_mode(enum spectator_mode sp_mode) +{ + printf("spectator mode\n"); + if(sp_mode == spectator_attack) + printf("attacker makes a move\n"); + else if(sp_mode == spectator_defense) + printf("defender make a move\n"); + else if(sp_mode == spectator_tossing) + printf("players toss in extra cards\n"); + else + printf("round result\n"); +} + +void pgf_game_result(int durak_position) +{ + printf("===============================\n" + " END OF GAME\n" + "player under number %u is durak\n" + "===============================\n", durak_position); +} diff --git a/client/printing_game_frames.h b/client/printing_game_frames.h index e3c844a..cd72932 100644 --- a/client/printing_game_frames.h +++ b/client/printing_game_frames.h @@ -10,5 +10,8 @@ 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(); +void pgf_spectator_mode(enum spectator_mode sp_mode); +void pgf_game_result(int durak_position); +void pgf_new_frame(); #endif diff --git a/server/server.c b/server/server.c index b2f1c3b..1655448 100644 --- a/server/server.c +++ b/server/server.c @@ -7,7 +7,6 @@ #include <fcntl.h> #include <syslog.h> #include <time.h> -#include <netinet/tcp.h> #include "server.h" #include "server_data_processing.h" @@ -35,7 +34,6 @@ static int accept_client(struct server *serv) struct session *new_session; socklen_t len = sizeof(addr); fd = accept(serv->listen_socket, (struct sockaddr*) &addr, &len); - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (int[]){1}, sizeof(int)); if(fd == -1) return -1; @@ -56,6 +54,10 @@ static int accept_client(struct server *serv) return 1; } +static void close_connection(struct server *serv) +{ +} + static int check_playable_player_number(struct server *serv) { return serv->connected_players_counter >= 2 && @@ -84,6 +86,7 @@ static void init_new_game(struct server *serv) #endif serv->turn_queue = malloc(sizeof(struct session*) * serv->connected_players_counter); + serv->turn_queue_size = 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); @@ -117,13 +120,15 @@ static void init_new_game(struct server *serv) for(i = 0; i < who_attack; ++i) shift_turn_queue_by_one(serv->turn_queue, serv->connected_players_counter); - update_card_quantity_arr(serv); + update_card_quantity_arr(serv->turn_queue, serv->cc); init_queue(&serv->cq); serv->gi = get_new_game_info(serv->connected_players_counter, serv->cc.number_arr, serv->shuffled_deck_size, serv->trump_card, serv->position_whose_turn, &serv->cq, &serv->cot); + serv->durak_position = 0; + serv->tossing_limit = 0; } static void set_whose_turn(struct server *serv, enum client_game_states state) @@ -141,6 +146,9 @@ static void set_whose_turn(struct server *serv, enum client_game_states state) } } +/* + * state set during game play + */ static void set_state_for_client(struct server *serv, enum client_game_states state) { @@ -159,7 +167,10 @@ static void set_state_for_client(struct server *serv, {} } - for(i = 0; i < serv->connected_players_counter; ++i) { + for(i = 0; i < serv->turn_queue_size; ++i) { + if(serv->turn_queue[i]->state == spectator) + continue; + switch(state) { case attack: if(serv->turn_queue[i] && serv->turn_queue[i] != @@ -193,6 +204,11 @@ static void set_state_for_client(struct server *serv, {} } } + /* end of game */ + if(state == result) + for(i = 0; i < serv->max_sess_arr_size; ++i) + if(serv->sess_arr[i]) + serv->sess_arr[i]->state = result; } static void set_record_status_for_all(struct server *serv) @@ -258,7 +274,7 @@ static void define_phase_after_defense(struct server *serv) 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->turn_queue_size, &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); @@ -276,7 +292,7 @@ static void define_phase_after_defense(struct server *serv) 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->turn_queue_size, &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); @@ -294,9 +310,8 @@ static void define_phase_after_defense(struct server *serv) set_state_for_client(serv, defense); set_whose_turn(serv, defense); serv->state = defense_phase_out; - } - /* defender can't defense */ -#if 0 + + /* defender can't defense */ } else { serv->turn_queue[1]->defense_lost = 1; put_all_cards_from_queue_to_table(&serv->cot, &serv->cq); @@ -308,15 +323,10 @@ static void define_phase_after_defense(struct server *serv) set_whose_turn(serv, tossing); serv->state = tossing_phase_out; } else { - move_all_cards_to_defender(&serv->cot, - &serv->turn_queue[1]->deck); - /* add shifting of turn arr*/ - set_state_for_client(serv, attack); - set_whose_turn(serv, attack); - serv->state = attack_phase_out; + set_state_for_client(serv, display_only_table); + serv->state = table; } } -#endif } } } @@ -334,7 +344,7 @@ static void define_phase_after_tossing(struct server *serv) 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->turn_queue_size, &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); @@ -364,7 +374,7 @@ static void define_phase_after_tossing(struct server *serv) serv->turn_queue[1]->deck, &serv->cq) && check_someone_can_toss_card(serv->turn_queue, - serv->connected_players_counter, + serv->turn_queue_size, &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); @@ -381,6 +391,9 @@ static void define_phase_after_tossing(struct server *serv) static void determine_server_state(struct server *serv) { + int key, turn_queue_resizing = 0; + struct session *defender = NULL; + switch(serv->state) { case no_players: serv->state = first_player; @@ -416,38 +429,129 @@ static void determine_server_state(struct server *serv) /* all answers received or the limit on card tossing was reached */ define_phase_after_tossing(serv); set_record_status_for_all(serv); - update_card_quantity_arr(serv); + update_card_quantity_arr(serv->turn_queue, serv->cc); update_game_info(serv->gi, serv->connected_players_counter, serv->shuffled_deck_size, serv->position_whose_turn); break; case table: - if(serv->turn_queue[1]->defense_lost) { - clear_defense_lost_status(serv->turn_queue[1]); - move_all_cards_to_defender(&serv->cot, &serv->turn_queue[1]->deck); - move_turn_queue_two_players_ahead(serv->turn_queue, - serv->connected_players_counter); + defender = serv->turn_queue[1]; + key = serv->turn_queue[0]->player_position-1; + update_card_quantity_arr(serv->turn_queue, serv->cc); + + /* ========= result of attacker's move ===========*/ + /* attacker was left without cards */ + if(!serv->shuffled_deck_size && !serv->cc.number_arr[key]) { + serv->turn_queue[0]->state = spectator; + /* resizing of turn_queue */ + shift_turn_queue_by_one(serv->turn_queue, serv->turn_queue_size); + --serv->turn_queue_size; + turn_queue_resizing = 1; } - else { + /* ========= result of defender's move =========== */ + if(defender->defense_lost) { + clear_defense_lost_status(defender); + move_all_cards_to_defender(&serv->cot, &defender->deck); + update_card_quantity_arr(serv->turn_queue, serv->cc); + if(!serv->shuffled_deck_size && serv->turn_queue_size == 1) { + serv->durak_position = defender->player_position; + set_state_for_client(serv, result); + serv->state = end_game; + } else { + turn_queue_resizing ? shift_turn_queue_by_one(serv->turn_queue, + serv->turn_queue_size) : + move_turn_queue_two_players_ahead(serv->turn_queue, + serv->turn_queue_size); + set_whose_turn(serv, attack); + set_state_for_client(serv, attack); + serv->state = attack_phase_out; + } + } else { remove_cards_from_table(&serv->cot); - shift_turn_queue_by_one(serv->turn_queue, - serv->connected_players_counter); + key = defender->player_position - 1; + if(!serv->shuffled_deck_size && !serv->cc.number_arr[key]) { + /* + * the final attack was completely beaten. + * The defender also has no cards left + */ + if(serv->turn_queue_size == 1) { + /* draw */ + serv->durak_position = 0; + set_state_for_client(serv, result); + serv->state = end_game; + } else { + /* attacker has no cards in current part*/ + if(turn_queue_resizing) { + shift_turn_queue_by_one(serv->turn_queue, + serv->turn_queue_size); + --serv->turn_queue_size; + defender->state = spectator; + set_state_for_client(serv, attack); + set_whose_turn(serv, attack); + serv->state = attack_phase_out; + /* third (last) player has cards */ + if(serv->turn_queue_size == 1) { + serv->durak_position = + serv->turn_queue[0]->player_position; + set_state_for_client(serv, result); + serv->state = end_game; + } + } else { + /* behind defender */ + move_turn_queue_two_players_ahead(serv->turn_queue, + serv->turn_queue_size); + --serv->turn_queue_size; + defender->state = spectator; + set_state_for_client(serv, attack); + set_whose_turn(serv, attack); + serv->state = attack_phase_out; + if(serv->turn_queue_size == 1) { + /* attacker is durak */ + serv->durak_position = + serv->turn_queue[0]->player_position; + set_state_for_client(serv, result); + serv->state = end_game; + } + } + } + } else { + if(serv->turn_queue_size == 1) { + serv->durak_position = defender->player_position; + set_state_for_client(serv, result); + serv->state = end_game; + } else { + if(!turn_queue_resizing) + shift_turn_queue_by_one(serv->turn_queue, + serv->turn_queue_size); + set_state_for_client(serv, attack); + set_whose_turn(serv, attack); + serv->state = attack_phase_out; + } + } } - set_record_status_for_all(serv); - set_state_for_client(serv, attack); - set_whose_turn(serv, attack); - /* - * update the number of cards to determine how many cards - * a player still needs to add - */ - update_card_quantity_arr(serv); - deal_cards(serv->shuffled_deck, &serv->shuffled_deck_size, - serv->turn_queue, serv->connected_players_counter, - serv->cc.number_arr); - /* update the card count after giving out */ - update_card_quantity_arr(serv); + /* ======== dealing cards =========== */ + if(serv->shuffled_deck_size) { + if(check_everyone_can_replanish_deck(serv->shuffled_deck_size, + serv->turn_queue, + serv->turn_queue_size, + serv->cc.number_arr)) + { + deal_cards(serv->shuffled_deck, &serv->shuffled_deck_size, + serv->turn_queue, serv->turn_queue_size, + serv->cc.number_arr); + } else + deal_one_card_in_turn(serv->shuffled_deck, + &serv->shuffled_deck_size, + serv->turn_queue, serv->turn_queue_size, + serv->cc); + /* update the card count after giving out cards */ + update_card_quantity_arr(serv->turn_queue, serv->cc); + } + update_game_info(serv->gi, serv->connected_players_counter, serv->shuffled_deck_size, serv->position_whose_turn); - serv->state = attack_phase_out; + set_record_status_for_all(serv); + turn_queue_resizing = 0; + serv->tossing_limit = 0; break; case defense_phase_out: serv->state = defense_phase_in; @@ -455,6 +559,9 @@ static void determine_server_state(struct server *serv) case tossing_phase_out: serv->state = tossing_phase_in; break; + case end_game: + close_connection(serv); + serv->state = no_players; } serv->change_server_state = 0; } @@ -518,6 +625,7 @@ static void set_up_player_tracking(struct server *serv, fd_set *readfds, case table: case defense_phase_out: case tossing_phase_out: + case end_game: if(serv->sess_arr[i]->record) { FD_SET(i, writefds); *maxfd = i > *maxfd ? i : *maxfd; @@ -549,8 +657,7 @@ static void set_up_player_tracking(struct server *serv, fd_set *readfds, } } -static int check_server_state_change_conditions(int is_tossing_limit, - struct server *serv) +static int check_server_state_change_conditions(struct server *serv) { switch(serv->state) { case start_game: @@ -560,12 +667,13 @@ static int check_server_state_change_conditions(int is_tossing_limit, case defense_phase_in: case tossing_phase_out: case table: + case end_game: return 1; case tossing_phase_in: - if(is_tossing_limit || + if(serv->tossing_limit || check_all_answers_were_received((const struct session**) serv->turn_queue, - serv->connected_players_counter)) + serv->turn_queue_size)) return 1; default: return 0; @@ -573,14 +681,10 @@ static int check_server_state_change_conditions(int is_tossing_limit, return 0; } -static void close_connection() -{ -} - static void make_data_transfer(struct server *serv, fd_set *readfds, fd_set *writefds) { - int i, result, tossing_limit = 0; + int i, result; for(i = 0; i < serv->max_sess_arr_size; ++i) { if(!serv->sess_arr[i]) continue; @@ -610,7 +714,8 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, case tossing_phase_out: case table: if(FD_ISSET(i, writefds) && serv->sess_arr[i]->record) - result = print_game_part(serv->sess_arr[i], serv->gi); + result = print_game_part(serv->sess_arr[i], serv->state, + serv->gi); serv->sess_arr[i]->record = 0; break; case attack_phase_in: @@ -627,7 +732,7 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, case tossing_phase_in: if(FD_ISSET(i, readfds)) { /* to determine that the player can no longer tossing */ - if(tossing_limit) + if(serv->tossing_limit) serv->sess_arr[i]->tm = cancel; result = get_cards_from_tossing_player(serv->sess_arr[i], @@ -637,22 +742,26 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, serv->sess_arr[i]->tm = answer_got; if(result == 2) - tossing_limit = 1; + serv->tossing_limit = 1; else if(result == 3) serv->sess_arr[i]->tm = cancel; } break; case no_players: {} + case end_game: + if(FD_ISSET(i, writefds) && serv->sess_arr[i]->record) + print_game_result(serv->sess_arr[i], serv->durak_position); + break; } } if(serv->state == start_game || serv->state == table) sleep(2); - if(check_server_state_change_conditions(tossing_limit, serv)) + if(check_server_state_change_conditions(serv)) serv->change_server_state = 1; /* connection is closed */ if(!result) - close_connection(); + close_connection(serv); } int main_loop(struct server *serv) diff --git a/server/server.h b/server/server.h index 86e0fca..3578606 100644 --- a/server/server.h +++ b/server/server.h @@ -26,7 +26,8 @@ enum server_states { defense_phase_in, tossing_phase_out, tossing_phase_in, - table + table, + end_game }; enum client_game_states { @@ -39,7 +40,9 @@ enum client_game_states { defense, tossing, card_acceptance_status, - tossing_limit_status + tossing_limit_status, + spectator, + result }; enum tossing_mode { @@ -49,6 +52,13 @@ enum tossing_mode { none }; +enum spectator_mode { + spectator_attack, + spectator_defense, + spectator_tossing, + spectator_table +}; + struct session { int fd; enum client_game_states state; @@ -90,10 +100,16 @@ struct server { const char *trump_card; struct game_info *gi; struct session **turn_queue; + /* changes if the player has discarded all his cards + * (and shuffled_deck_size == 0) + */ + int turn_queue_size; struct card_count cc; int position_whose_turn; struct card_queue cq; struct cards_on_table cot; + int durak_position; + int tossing_limit; }; #endif diff --git a/server/server_data_processing.c b/server/server_data_processing.c index b7b2374..fc81996 100644 --- a/server/server_data_processing.c +++ b/server/server_data_processing.c @@ -63,7 +63,9 @@ int check_readiness(struct session *client) } /* * example: 10#\A^\7v'\n' - * or 0'\n' + * or: 10#\A^\7v: + * or: ='\n' + * or: =: */ static void copy_card_queue(int *offset, struct card_queue *cq) { @@ -84,7 +86,7 @@ static void copy_card_queue(int *offset, struct card_queue *cq) /* * example: 10#+\+Q#+A^+\+-+7v: - * or 0: + * or =: */ static void copy_cards_on_table(int *offset, struct cards_on_table cot) { @@ -102,8 +104,8 @@ static void copy_cards_on_table(int *offset, struct cards_on_table cot) /* * example: 10#\A^\7v: * or 10#\A^\7v'\n' - * or 0: - * or 0'\n' + * or =: + * or ='\n' */ static void copy_own_deck(int *offset, player_cards deck) { @@ -153,8 +155,10 @@ static void copy_base_info(int *free_pos, struct game_info *gi, *free_pos += sprintf(output_buffer + *free_pos, "=:"); } -int print_game_part(const struct session *client, struct game_info *gi) +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, @@ -181,6 +185,7 @@ int print_game_part(const struct session *client, struct game_info *gi) *(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); @@ -189,6 +194,17 @@ int print_game_part(const struct session *client, struct game_info *gi) 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: {} @@ -315,6 +331,10 @@ int get_cards_from_tossing_player(struct session *client, 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 */ @@ -342,9 +362,6 @@ int get_cards_from_tossing_player(struct session *client, given_card[j] = client->buffer[i]; ++j; } - /* cancellation */ - if(client->buffer[0] == '\n') - return 3; /* 7 -- state for result of received cards */ data_length = sprintf(output_buffer, "%d:%s\n", card_acceptance_status, @@ -355,3 +372,12 @@ int get_cards_from_tossing_player(struct session *client, 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); +} diff --git a/server/server_data_processing.h b/server/server_data_processing.h index 875fd98..e6c1ab0 100644 --- a/server/server_data_processing.h +++ b/server/server_data_processing.h @@ -6,7 +6,9 @@ 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); + /* for define spectator mode */ +int print_game_part(const struct session *client, enum server_states ss, + struct game_info *gi); int get_cards_from_attacker(struct session *client, const struct cards_on_table *cot, const player_cards defense_deck, @@ -17,5 +19,6 @@ int get_cards_from_tossing_player(struct session *client, const player_cards defense_deck, struct cards_on_table *cot, struct card_queue *cq); +void print_game_result(const struct session *client, int durak_position); #endif diff --git a/server/server_game_process.c b/server/server_game_process.c index 46a9535..d6fc4be 100644 --- a/server/server_game_process.c +++ b/server/server_game_process.c @@ -52,15 +52,15 @@ 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) + struct session **turn_queue, int turn_queue_size, + int *number_arr) { int i, j, key, player_deck_size, card_shortage_quantity, last_idx; const char *extracted_card = NULL; - for(i = 0; i < players_number; ++i) { + for(i = 0; i < turn_queue_size; ++i) { key = turn_queue[i]->player_position - 1; - player_deck_size = card_quantity_arr[key]; + player_deck_size = number_arr[key]; if(player_deck_size < start_deck_size) { card_shortage_quantity = start_deck_size - player_deck_size; for(j = 0; j < card_shortage_quantity; ++j) { @@ -77,6 +77,32 @@ void deal_cards(const char **shuffled_deck, int *shuffled_cards_left, } } +void deal_one_card_in_turn(const char **shuffled_deck, int *shuffled_cards_left, + struct session **turn_queue, int turn_queue_size, + struct card_count cc) +{ + int i, key, player_deck_size, last_idx; + const char *extracted_card = NULL; + + while(*shuffled_cards_left) { + update_card_quantity_arr(turn_queue, cc); + for(i = 0; i < turn_queue_size; ++i) { + key = turn_queue[i]->player_position - 1; + player_deck_size = cc.number_arr[key]; + if(player_deck_size < start_deck_size) { + last_idx = *shuffled_cards_left-1; + /* shuffled deck is empty */ + if(last_idx < 0) + return; + extracted_card = shuffled_deck[last_idx]; + push_stack(&turn_queue[i]->deck, extracted_card); + --*shuffled_cards_left; + shuffled_deck[last_idx] = NULL; + } + } + } +} + const char* extract_trump_card(const char **shuffled_deck, int *cards_left) { const char *trump_card = NULL; @@ -148,34 +174,49 @@ int find_lowest_trump(player_cards deck, const char *trump_suit) } return lowest_rank; } - -void shift_turn_queue_by_one(struct session **turn_queue, int size) +/* + * used to transition attack to defender + */ +void shift_turn_queue_by_one(struct session **turn_queue, int turn_queue_size) { int i; struct session *tmp = turn_queue[0]; - for(i = 1; i < size; ++i) + for(i = 1; i < turn_queue_size; ++i) turn_queue[i-1] = turn_queue[i]; turn_queue[i-1] = tmp; } -void move_turn_queue_two_players_ahead(struct session **turn_queue, int size) +/* + * used to transition the attack to player behind defender + */ +void move_turn_queue_two_players_ahead(struct session **turn_queue, + int turn_queue_size) { int i; for(i = 0; i < 2; ++i) - shift_turn_queue_by_one(turn_queue, size); + shift_turn_queue_by_one(turn_queue, turn_queue_size); } -void update_card_quantity_arr(struct server *serv) +void update_card_quantity_arr(struct session **turn_queue, struct card_count cc) { - int i, player_position_idx; + int i, key; + for(i = 0; i <= cc.number_arr_idx; ++i) { + key = turn_queue[i]->player_position - 1; + cc.number_arr[key] = + find_out_card_quantity_in_deck(turn_queue[i]->deck); + } + + +#if 0 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->cc.number_arr[player_position_idx] = find_out_card_quantity_in_deck(serv->sess_arr[i]->deck); } +#endif } struct game_info* get_new_game_info(int players_number, int *card_quantity_arr, @@ -358,7 +399,7 @@ static int check_matched_ranks(const char *attack_card, } int check_someone_can_toss_card(struct session **turn_queue, - int players_quantity, + int players_quantity, /* like turn_queue_size */ struct card_queue *cq, struct cards_on_table *cot) { @@ -523,11 +564,12 @@ int calculate_attack_card_quantity_on_table(const struct cards_on_table *cot) return counter; } -int check_all_answers_were_received(const struct session **turn_queue, int size) +int check_all_answers_were_received(const struct session **turn_queue, + int turn_queue_size) { int i; - for(i = 0; i < size; ++i) + for(i = 0; i < turn_queue_size; ++i) if(turn_queue[i]->tm == answer_wait) return 0; return 1; @@ -558,3 +600,34 @@ void clear_defense_lost_status(struct session *defender) { defender->defense_lost = 0; } +/* + * can everyone fully replenish their deck (up to 6 cards)? + */ +int check_everyone_can_replanish_deck(int shuffled_cards_left, + struct session **turn_queue, + int turn_queue_size, int *number_arr) +{ + int i, key, player_deck_size; + + for(i = 0; i < turn_queue_size; ++i) { + key = turn_queue[i]->player_position - 1; + player_deck_size = number_arr[key]; + if(player_deck_size < start_deck_size) + shuffled_cards_left -= start_deck_size - player_deck_size; + } + return shuffled_cards_left >= 0; +} +#if 0 +void find_out_who_dropped_all_cards(struct session **turn_queue, + int turn_queue_size, int *number_arr) +{ + int i, key, player_deck_size; + + for(i = 0; i < turn_queue_size; ++i) { + key = turn_queue[i]->player_position - 1; + player_deck_size = number_arr[key]; + if(!player_deck_size) + turn_queue[i]->state = discarded_cards; + } +} +#endif diff --git a/server/server_game_process.h b/server/server_game_process.h index 9338c25..f384fdc 100644 --- a/server/server_game_process.h +++ b/server/server_game_process.h @@ -23,16 +23,21 @@ const char** get_shuffled_deck(); void deal_first_cards(const char **shuffled_deck, int *cards_left, player_cards *deck); void deal_cards(const char **shuffled_deck, int *shuffled_cards_left, - struct session **turn_queue, int players_number, - int *card_quantity_arr); + struct session **turn_queue, int turn_queue_size, + int *number_arr); +void deal_one_card_in_turn(const char **shuffled_deck, int *shuffled_cards_left, + struct session **turn_queue, int turn_queue_size, + struct card_count cc); 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); -void update_card_quantity_arr(struct server *serv); +void shift_turn_queue_by_one(struct session **turn_queue, int turn_queue_size); +void move_turn_queue_two_players_ahead(struct session **turn_queue, + int turn_queue_size); +void update_card_quantity_arr(struct session **turn_queue, + struct card_count cc); struct game_info* get_new_game_info(int players_number, int *card_quantity_arr, int shuffled_cards_left, @@ -71,10 +76,15 @@ void remove_cards_from_table(struct cards_on_table *cot); 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 turn_queue_size); int is_receiving_cards_limit(const struct cards_on_table *cot, player_cards defense_deck, const struct card_queue *cq); void clear_defense_lost_status(struct session *defender); +int check_everyone_can_replanish_deck(int shuffled_cards_left, + struct session **turn_queue, + int turn_queue_size, int *number_arr); +void find_out_who_dropped_all_cards(struct session **turn_queue, + int turn_queue_size, int *number_arr); #endif |