back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
path: root/server/server.c
diff options
context:
space:
mode:
authorscratko <m@scratko.xyz>2024-08-16 18:10:11 +0300
committerscratko <m@scratko.xyz>2024-08-16 18:10:11 +0300
commiteb90648bdad1443c9cfc72e903a93642e10a0ab7 (patch)
treedc567a9aa834bb0d5f3429e8a38910990d75e4eb /server/server.c
parent880b8be2c28d761505b2eecc1386919d5add6f2f (diff)
downloaddurak-eb90648bdad1443c9cfc72e903a93642e10a0ab7.tar.gz
durak-eb90648bdad1443c9cfc72e903a93642e10a0ab7.tar.bz2
durak-eb90648bdad1443c9cfc72e903a93642e10a0ab7.zip
Global fixes v2.0
Added spectator mode. Added screen of game result. Added definition of durak. If not all players can replenish their decks, they take cards one at a time in turn.
Diffstat (limited to 'server/server.c')
-rw-r--r--server/server.c219
1 files changed, 164 insertions, 55 deletions
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)