From b4b784928cbec4a93c71f3ca1e37a14397929edb Mon Sep 17 00:00:00 2001 From: scratko Date: Sun, 18 Aug 2024 22:24:30 +0300 Subject: Final version v1.0 Fixed stack clearing. Added check for NULL before clearing game parameters. Added refactoring of define_phase_after_attack(). Analyzing game results is organized into several functions. Fixed card limit detection on tossing (line 366 in server_data_processing.c). --- server/server.c | 374 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 212 insertions(+), 162 deletions(-) (limited to 'server/server.c') diff --git a/server/server.c b/server/server.c index 8ebc937..6a9075c 100644 --- a/server/server.c +++ b/server/server.c @@ -70,14 +70,22 @@ static void close_connection(struct server *serv) serv->sess_arr[i] = NULL; } serv->connected_players_counter = 0; - free(serv->cc.number_arr); - free(serv->shuffled_deck); - free(serv->turn_queue); - free(serv->gi); - serv->cc.number_arr = NULL; - serv->shuffled_deck = NULL; - serv->turn_queue = NULL; - serv->gi = NULL; + if(serv->cc.number_arr) { + free(serv->cc.number_arr); + serv->cc.number_arr = NULL; + } + if(serv->shuffled_deck) { + free(serv->shuffled_deck); + serv->shuffled_deck = NULL; + } + if(serv->turn_queue) { + free(serv->turn_queue); + serv->turn_queue = NULL; + } + if(serv->gi) { + free(serv->gi); + serv->gi = NULL; + } clear_queue(&serv->cq); } @@ -239,6 +247,7 @@ static void set_record_status_for_all(struct server *serv) serv->sess_arr[i]->record = 1; } +#if 0 static int print_table_condition(struct server *serv) { return !check_defender_can_defend(&serv->cq, serv->turn_queue[1]->deck, @@ -247,22 +256,45 @@ static int print_table_condition(struct server *serv) serv->connected_players_counter, &serv->cq, &serv->cot); } +#endif static int defense_condition(struct server *serv) { 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(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); + serv->state = defense_phase_out; + /* defender can't keep defense */ + } 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, + serv->connected_players_counter, + &serv->cq, &serv->cot) && + !is_receiving_cards_limit(&serv->cot, serv->turn_queue[1]->deck, + &serv->cq)) + { + set_state_for_client(serv, tossing); + set_whose_turn(serv, tossing); + serv->state = tossing_phase_out; + } else { + set_state_for_client(serv, display_only_table); + serv->state = end_round; + } + } +#if 0 if(print_table_condition(serv)) { set_state_for_client(serv, display_only_table); put_all_cards_from_queue_to_table(&serv->cot, &serv->cq); serv->turn_queue[1]->defense_lost = 1; - serv->state = table; + serv->state = end_round; } else if(defense_condition(serv)) { set_state_for_client(serv, defense); set_whose_turn(serv, defense); @@ -274,14 +306,14 @@ static void define_phase_after_attack(struct server *serv) 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; + serv->state = end_round; } else { set_state_for_client(serv, tossing); set_whose_turn(serv, tossing); serv->state = tossing_phase_out; } - } +#endif } static void define_phase_after_defense(struct server *serv) @@ -303,7 +335,7 @@ static void define_phase_after_defense(struct server *serv) /* then begin new attack */ } else { set_state_for_client(serv, display_only_table); - serv->state = table; + serv->state = end_round; } /* can defender continue defense? */ } else { @@ -320,7 +352,7 @@ static void define_phase_after_defense(struct server *serv) serv->state = tossing_phase_out; } else { set_state_for_client(serv, display_only_table); - serv->state = table; + serv->state = end_round; } /* card queue contains some cards for defender */ } else { @@ -344,7 +376,7 @@ static void define_phase_after_defense(struct server *serv) serv->state = tossing_phase_out; } else { set_state_for_client(serv, display_only_table); - serv->state = table; + serv->state = end_round; } } } @@ -355,31 +387,31 @@ static void define_phase_after_tossing(struct server *serv) { if(serv->turn_queue[1]->defense_lost) { if(is_empty_queue(&serv->cq)) { - /* nobody's put any cards on the table */ + /* nobody's put any cards on the end_round */ set_state_for_client(serv, display_only_table); - serv->state = table; + serv->state = end_round; } else { 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) && + &serv->cq) && check_someone_can_toss_card(serv->turn_queue, - serv->turn_queue_size, - &serv->cq, &serv->cot)) + serv->turn_queue_size, + &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); set_whose_turn(serv, tossing); serv->state = tossing_phase_out; } else { set_state_for_client(serv, display_only_table); - serv->state = table; + serv->state = end_round; } } /* defense continue? */ } else { if(is_empty_queue(&serv->cq)) { set_state_for_client(serv, display_only_table); - serv->state = table; + serv->state = end_round; } else { if(check_defender_can_defend(&serv->cq, serv->turn_queue[1]->deck, serv->trump_suit)) { @@ -391,29 +423,166 @@ static void define_phase_after_tossing(struct server *serv) serv->turn_queue[1]->defense_lost = 1; 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) && + serv->turn_queue[1]->deck, + &serv->cq) && check_someone_can_toss_card(serv->turn_queue, - serv->turn_queue_size, - &serv->cq, &serv->cot)) + serv->turn_queue_size, + &serv->cq, &serv->cot)) { set_state_for_client(serv, tossing); set_whose_turn(serv, tossing); serv->state = tossing_phase_out; } else { set_state_for_client(serv, display_only_table); - serv->state = table; + serv->state = end_round; } } } } } -static void determine_server_state(struct server *serv) +static void analyze_attackers_move(struct server *serv, + int *turn_queue_resizing, + struct session **defender) +{ + + int key; + key = serv->turn_queue[0]->player_position-1; + *defender = serv->turn_queue[1]; + + /* 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; + } +} + +static void analyze_defenders_move(struct server *serv, int turn_queue_resizing, + struct session *defender) { - int key, turn_queue_resizing = 0; + int key; + + 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); + 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; + } + } + } +} + +static void analyze_end_round(struct server *serv) +{ + int turn_queue_resizing = 0; struct session *defender = NULL; + update_card_quantity_arr(serv->turn_queue, serv->cc); + + /* ========= result of attacker's move ===========*/ + analyze_attackers_move(serv, &turn_queue_resizing, &defender); + /* ========= result of defender's move =========== */ + analyze_defenders_move(serv, turn_queue_resizing, defender); +} + +static void dealing_cards_phase(struct server *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); + } +} + +static void determine_server_state(struct server *serv) +{ switch(serv->state) { case no_players: serv->state = first_player; @@ -453,124 +622,12 @@ static void determine_server_state(struct server *serv) update_game_info(serv->gi, serv->connected_players_counter, serv->shuffled_deck_size, serv->position_whose_turn); break; - case table: - 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; - } - /* ========= 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); - 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; - } - } - } - /* ======== 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); - } - + case end_round: + analyze_end_round(serv); + dealing_cards_phase(serv); update_game_info(serv->gi, serv->connected_players_counter, serv->shuffled_deck_size, serv->position_whose_turn); set_record_status_for_all(serv); - turn_queue_resizing = 0; serv->tossing_limit = 0; break; case defense_phase_out: @@ -637,7 +694,7 @@ static void set_up_player_tracking(struct server *serv, fd_set *readfds, break; case start_game: case attack_phase_out: - case table: + case end_round: case defense_phase_out: case tossing_phase_out: case end_game: @@ -681,7 +738,7 @@ static int check_server_state_change_conditions(struct server *serv) case defense_phase_out: case defense_phase_in: case tossing_phase_out: - case table: + case end_round: case end_game: return 1; case tossing_phase_in: @@ -730,7 +787,7 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, case attack_phase_out: case defense_phase_out: case tossing_phase_out: - case table: + case end_round: if(FD_ISSET(i, writefds) && serv->sess_arr[i]->record) result = print_game_part(serv->sess_arr[i], serv->state, serv->gi); @@ -756,10 +813,10 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, get_cards_from_tossing_player(serv->sess_arr[i], serv->turn_queue[1]->deck, &serv->cot, &serv->cq); - if(result == answer_got || result == anwer_got_with_limit) + if(result == answer_got || result == answer_got_with_limit) serv->sess_arr[i]->tm = answer_got; - if(result == anwer_got_with_limit) + if(result == answer_got_with_limit) serv->tossing_limit = 1; else if(result == cancel) serv->sess_arr[i]->tm = cancel; @@ -779,7 +836,7 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, result = 1; /* next can be reading that's not ready */ } } - if(serv->state == start_game || serv->state == table || + if(serv->state == start_game || serv->state == end_round || serv->state == end_game) sleep(2); if(check_server_state_change_conditions(serv)) @@ -859,12 +916,14 @@ static int init_server(struct server *serv, int port) serv->shuffled_deck_size = max_shuffled_deck_size; serv->gi = NULL; serv->cc.number_arr = NULL; + serv->turn_queue = NULL; + serv->cq.first = NULL; + serv->cq.last = NULL; listen(serv->listen_socket, listen_qlen); return 1; } -#if 0 static void demonization() { int pid; @@ -884,7 +943,6 @@ static void demonization() if(pid) exit(0); } -#endif int main(int argc, char **argv) { @@ -896,25 +954,17 @@ int main(int argc, char **argv) "Usage: \n"); return 1; } -#if 0 demonization(); -#endif srand(time(NULL)); -#if 0 openlog("durak server", 0, LOG_USER); syslog(LOG_INFO, "daemon started"); -#endif port = strtol(argv[1], NULL, 10); if(!init_server(&serv, port)) { -#if 0 syslog(LOG_ERR, "server initialization error"); -#endif return 2; } return main_loop(&serv); -#if 0 syslog(LOG_INFO, "server terminated"); closelog(); -#endif } -- cgit v1.2.3