back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
path: root/server/server.c
diff options
context:
space:
mode:
authorscratko <m@scratko.xyz>2024-08-18 22:24:30 +0300
committerscratko <m@scratko.xyz>2024-08-18 22:24:30 +0300
commitb4b784928cbec4a93c71f3ca1e37a14397929edb (patch)
treeefb86b0a710f22337c3319bedc7870488801896f /server/server.c
parent9970a2275a56d7835ba0c12a8586dc25cf7ec1cf (diff)
downloaddurak-b4b784928cbec4a93c71f3ca1e37a14397929edb.tar.gz
durak-b4b784928cbec4a93c71f3ca1e37a14397929edb.tar.bz2
durak-b4b784928cbec4a93c71f3ca1e37a14397929edb.zip
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).
Diffstat (limited to 'server/server.c')
-rw-r--r--server/server.c374
1 files changed, 212 insertions, 162 deletions
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: <port>\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
}