back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--client/client.c20
-rw-r--r--client/client.h13
-rw-r--r--client/data_decryption.c16
-rw-r--r--client/data_decryption.h4
-rw-r--r--client/printing_game_frames.c32
-rw-r--r--client/printing_game_frames.h3
-rw-r--r--server/server.c219
-rw-r--r--server/server.h20
-rw-r--r--server/server_data_processing.c42
-rw-r--r--server/server_data_processing.h5
-rw-r--r--server/server_game_process.c101
-rw-r--r--server/server_game_process.h22
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