back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscratko <m@scratko.xyz>2024-08-14 02:35:56 +0300
committerscratko <m@scratko.xyz>2024-08-14 02:35:56 +0300
commit880b8be2c28d761505b2eecc1386919d5add6f2f (patch)
tree63e965c3f82bcd09bb07baf9b669a736293dddc7
parenta2d696dea797faaa3157046c8ae89cd70e965bff (diff)
downloaddurak-880b8be2c28d761505b2eecc1386919d5add6f2f.tar.gz
durak-880b8be2c28d761505b2eecc1386919d5add6f2f.tar.bz2
durak-880b8be2c28d761505b2eecc1386919d5add6f2f.zip
Global fixes v1.0
Defense hint now only takes into account unbeaten cards. The client accounts for sticky data in one packet via TCP. Changed delimiter when sending data related to cards on the table and the queue (from '0' to '='). Accepting cards from a client (verification_client_input.c) is heavily patched. Cards are taken from the stack at the hint's prompt. Added pop_stack(). The trump card is retrieved from the end of the array. Changed the check of the defender's ability to beat all cards.
-rw-r--r--client/card_stack.c39
-rw-r--r--client/card_stack.h2
-rw-r--r--client/client.c34
-rw-r--r--client/client.h1
-rw-r--r--client/data_decryption.c12
-rw-r--r--client/printing_game_frames.c18
-rw-r--r--client/verification_client_input.c67
-rw-r--r--server/card_stack.c9
-rw-r--r--server/card_stack.h1
-rw-r--r--server/server.c38
-rw-r--r--server/server.h2
-rw-r--r--server/server_data_processing.c38
-rw-r--r--server/server_game_process.c121
-rw-r--r--server/server_game_process.h2
14 files changed, 311 insertions, 73 deletions
diff --git a/client/card_stack.c b/client/card_stack.c
index 5d0700b..d9dc273 100644
--- a/client/card_stack.c
+++ b/client/card_stack.c
@@ -81,11 +81,32 @@ void add_hint_letters_stack(player_cards deck)
}
}
+static int check_no_attackers_cards_marked(player_cards deck)
+{
+ while(deck) {
+ if(deck->is_usable)
+ return 0;
+ deck = deck->next;
+ }
+ return 1;
+}
+
+static void mark_all_card_stack(player_cards deck)
+{
+ player_cards tmp_deck = deck;
+
+ while(tmp_deck) {
+ tmp_deck->is_usable = 1;
+ tmp_deck = tmp_deck->next;
+ }
+}
+
void mark_card_for_attackers_stack(player_cards deck)
{
char *card = NULL, *found_card;
struct card_stack_item *search_deck = NULL;
int target_rank, found_rank;
+ player_cards tmp_begin_deck = deck;
while(deck) {
/* is the card already marked? */
@@ -103,12 +124,16 @@ void mark_card_for_attackers_stack(player_cards deck)
}
found_card = search_deck->str;
found_rank = convert_rank_to_int(found_card);
- if(found_rank == target_rank)
+ if(found_rank == target_rank) {
+ deck->is_usable = 1;
search_deck->is_usable = 1;
+ }
search_deck = search_deck->next;
}
deck = deck->next;
}
+ if(check_no_attackers_cards_marked(tmp_begin_deck))
+ mark_all_card_stack(tmp_begin_deck);
}
#if 0
static int is_card_beaten(const char *attack_card, const char *defend_card,
@@ -142,8 +167,8 @@ void mark_card_for_defenders_stack(player_cards deck,
while(deck) {
for(i = 0; i <= cot->card_arr_idx; ++i)
- if((i == 0 || !(i % 3)) && is_card_beaten(cot->card_arr[i],
- deck->str, trump_suit))
+ if(((i == 0 || !(i % 3)) && cot->card_arr[i+2][0] == '-') &&
+ is_card_beaten(cot->card_arr[i], deck->str, trump_suit))
{
deck->is_usable = 1;
break;
@@ -179,15 +204,15 @@ void mark_card_for_tossing_stack(player_cards deck, struct cards_on_table *cot)
deck = deck->next;
}
}
-
-int card_search_by_letter(player_cards deck, int letter)
+/* rename: and_unmarked */
+char* card_search_by_letter(player_cards deck, int letter)
{
while(deck) {
if(deck->tip == letter && deck->is_usable) {
deck->is_usable = 0;
- return 1;
+ return deck->str;
}
deck = deck->next;
}
- return 0;
+ return NULL;
}
diff --git a/client/card_stack.h b/client/card_stack.h
index 7cb5798..ba973f4 100644
--- a/client/card_stack.h
+++ b/client/card_stack.h
@@ -24,6 +24,6 @@ void mark_card_for_defenders_stack(player_cards deck,
struct cards_on_table *cot,
char* trump_suit);
void mark_card_for_tossing_stack(player_cards deck, struct cards_on_table *cot);
-int card_search_by_letter(player_cards deck, int letter);
+char* card_search_by_letter(player_cards deck, int letter);
#endif
diff --git a/client/client.c b/client/client.c
index d932a51..4abcf7d 100644
--- a/client/client.c
+++ b/client/client.c
@@ -4,6 +4,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+#include <stdio.h> /* test */
#include "client.h"
#include "data_decryption.h"
@@ -15,15 +16,23 @@ static const int port = 8082;
static void get_data_from_server(struct client *cl, fd_set *readfds)
{
+ int i;
int update_info = 0;
/* pointer to delimeter (:) that is behind extract data */
char *end_p;
if(FD_ISSET(cl->fd, readfds)) {
- read(cl->fd, cl->buffer, max_buffer_size);
+ if(!cl->data_left_in_buffer) {
+ cl->data_left_in_buffer = read(cl->fd, cl->buffer, max_buffer_size);
+ printf("%d\n", cl->data_left_in_buffer);
+ for(i = 0; i < cl->data_left_in_buffer; ++i)
+ putchar(cl->buffer[i]);
+ putchar('\n');
+ }
decrypt_set_state(cl, &end_p);
update_info = 1;
cl->display_new_frame = 1;
+ cl->pending_server_response = 0;
}
if(update_info) {
switch(cl->state) {
@@ -50,13 +59,20 @@ static void get_data_from_server(struct client *cl, fd_set *readfds)
decrypt_set_card_queue(cl, end_p+1);
break;
case card_acceptance_status:
- decrypt_set_card_acceptance_status(cl, cl->buffer);
+ decrypt_set_card_acceptance_status(cl, end_p+1);
break;
/* no data to extract */
case tossing_limit_status:
default:
{}
}
+ for(i = 0; cl->buffer[i] != '\n'; ++i)
+ {}
+ if((cl->buffer+i - cl->buffer + 1) != cl->data_left_in_buffer) {
+ cl->data_left_in_buffer -= i + 1;
+ memmove(cl->buffer, cl->buffer+i+1, cl->data_left_in_buffer);
+ } else
+ cl->data_left_in_buffer = 0;
}
}
@@ -66,7 +82,7 @@ static void prepare_tips_for_client(struct client *cl)
if(!is_empty_stack(cl->deck))
add_hint_letters_stack(cl->deck);
-
+/* TODO: clear marked cards ??? */
switch(cl->state) {
case attack:
mark_card_for_attackers_stack(cl->deck);
@@ -126,7 +142,7 @@ static void change_client_frame(struct client *cl)
static void send_data_to_server(struct client *cl, fd_set *readfds)
{
- int input_result;
+ int input_result = 0;
if(FD_ISSET(0, readfds)) { /* 0 - stdin */
read(0, cl->buffer, max_buffer_size);
@@ -181,9 +197,11 @@ int main_loop(struct client *cl)
if(check_tracking_client_input(cl->state, cl->pending_server_response))
FD_SET(0, &readfds);
- select_result = select(cl->fd + 1, &readfds, NULL, NULL, NULL);
- if(select_result == -1)
- return 2;
+ if(!cl->data_left_in_buffer) {
+ select_result = select(cl->fd + 1, &readfds, NULL, NULL, NULL);
+ if(select_result == -1)
+ return 2;
+ }
get_data_from_server(cl, &readfds);
prepare_tips_for_client(cl);
if(cl->display_new_frame)
@@ -210,6 +228,7 @@ static void init_client(struct client *cl)
cl->position_whose_turn = 0;
cl->display_new_frame = 0;
cl->all_input_cards_accepted = 0;
+ cl->data_left_in_buffer = 0;
}
/*
@@ -222,6 +241,7 @@ static int connect_to_server(struct client *cl)
struct sockaddr_in addr;
cl->fd = socket(AF_INET, SOCK_STREAM, 0);
+
if(cl->fd == -1)
return 0;
addr.sin_family = AF_INET;
diff --git a/client/client.h b/client/client.h
index f73cdce..9bdd8cc 100644
--- a/client/client.h
+++ b/client/client.h
@@ -66,6 +66,7 @@ struct client {
int position_whose_turn;
int display_new_frame;
int all_input_cards_accepted;
+ int data_left_in_buffer;
};
#endif
diff --git a/client/data_decryption.c b/client/data_decryption.c
index 2d10561..b445454 100644
--- a/client/data_decryption.c
+++ b/client/data_decryption.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
void decrypt_set_state(struct client *cl, char **end_p)
{
@@ -24,11 +25,9 @@ static void decrypt_set_trump_card(struct client *cl, char *start_p,
{
int i;
- for(i = 0; *start_p != '\0'; ++start_p, ++i)
+ for(i = 0; *start_p != ':'; ++start_p, ++i)
cl->trump_card[i] = *start_p;
cl->trump_card[i] = '\0';
- /* move to : */
- ++start_p;
*end_p = start_p;
}
@@ -65,7 +64,7 @@ void decrypt_set_base_info(struct client *cl, char *start_p, char **end_p)
i = 0, j = 0;
for(start_p = *end_p + 1; *start_p != ':'; ++start_p) {
/* empty table */
- if(*start_p == '0') {
+ if(*start_p == '=') {
/* to delimiter : */
++start_p;
i = -1;
@@ -94,7 +93,7 @@ void decrypt_set_base_info(struct client *cl, char *start_p, char **end_p)
for(++start_p, i = 0; *start_p != ':' && *start_p != '\n'; ++start_p) {
/* empty deck */
- if(*start_p == '0') {
+ if(*start_p == '=') {
i = -1;
/* to delimiter ':' or '\n' */
++start_p;
@@ -107,6 +106,7 @@ void decrypt_set_base_info(struct client *cl, char *start_p, char **end_p)
strcpy(card, tmp_card);
push_stack(&cl->deck, card);
i = 0;
+ continue;
}
tmp_card[i] = *start_p;
++i;
@@ -132,7 +132,7 @@ void decrypt_set_card_queue(struct client *cl, char *start_p)
for(i = 0, j = 0; *start_p != '\n'; ++start_p) {
/* empty queue */
- if(*start_p == '0') {
+ if(*start_p == '=') {
i = -1;
break;
}
diff --git a/client/printing_game_frames.c b/client/printing_game_frames.c
index 38f1a78..f75cec5 100644
--- a/client/printing_game_frames.c
+++ b/client/printing_game_frames.c
@@ -5,17 +5,17 @@
void pgf_first_player()
{
- printf("======================================="
- " You're the first player"
- "Waiting for other players to connect..."
+ printf("=======================================\n"
+ " You're the first player\n"
+ "Waiting for other players to connect...\n"
"=======================================\n");
}
void pgf_confirmation_waiting(int total_players)
{
- printf("======================================="
- " To start game press <Enter> key "
- "Connected players: %u/8 "
+ printf("=======================================\n"
+ " To start game press <Enter> key \n"
+ "Connected players: %u/8 \n"
"=======================================\n", total_players);
}
@@ -24,7 +24,7 @@ void pgf_table(struct client *cl)
struct card_stack_item *deck = NULL;
int i;
- for(i = 0; i < cl->cc.number_arr_idx; ++i)
+ for(i = 0; i <= cl->cc.number_arr_idx; ++i)
/* printing who will move */
if(cl->state == attack_expectation || cl->state == defense_expectation)
printf("<%c%u > ", cl->position_whose_turn-1 == i ? '*' : ' ',
@@ -41,7 +41,8 @@ void pgf_table(struct client *cl)
if(cl->state == defense_expectation)
for(i = 0; i <= cl->cq.card_arr_idx; ++i)
printf(" %s \\ -\n", cl->cq.card_arr[i]);
- printf("\n\n");
+ if(cl->cot.card_arr_idx != -1)
+ printf("\n\n");
/* ================ player's deck ================ */
deck = cl->deck;
i = 0;
@@ -70,6 +71,7 @@ void pgf_suggestions(struct client *cl)
deck = deck->next;
}
printf(" > ");
+ fflush(stdout);
}
void pgf_select_idle_mode_message(enum client_states state)
diff --git a/client/verification_client_input.c b/client/verification_client_input.c
index 2134f30..1530387 100644
--- a/client/verification_client_input.c
+++ b/client/verification_client_input.c
@@ -1,7 +1,15 @@
#include "verification_client_input.h"
+#include "card_handling.h"
#include <stdio.h>
#include <unistd.h>
+#include <string.h>
+
+enum {
+ output_buffer_size = 1024
+};
+
+static char output_buffer[output_buffer_size];
/*
* 1 - response received
@@ -18,29 +26,70 @@ int vci_confirmation_waiting(int fd, char *buffer)
return 0;
}
+/*
+ * example: A#\A^\Av\'\n'
+ * or (while tossing): '\n'
+ */
int vci_attack_or_tossing(int fd, char *buffer, player_cards deck,
enum client_states state)
{
- int i;
+ int i, free_pos = 0;
+ char * card = NULL;
- if(state == tossing && buffer[0] == '\n') /* cancel card tossing */
+ if(state == tossing && buffer[0] == '\n') { /* cancel card tossing */
+ write(fd, buffer, 1);
return 1;
+ }
for(i = 0; buffer[i] != '\n'; ++i)
- if(!card_search_by_letter(deck, buffer[i])) {
+ if((card = card_search_by_letter(deck, buffer[i])) != NULL) {
+#if 0
+ if(!rank)
+ rank = convert_rank_to_int(card);
+ if(rank == convert_rank_to_int(card)) {
+#endif
+ strncpy(output_buffer + free_pos, card, strlen(card));
+ free_pos += strlen(card);
+ output_buffer[free_pos] = '\\';
+ ++free_pos;
+#if 0
+ } else {
+ printf("incorrect input\n");
+ return 0;
+ }
+#endif
+ } else {
printf("incorrect input\n");
return 0;
}
+ output_buffer[free_pos] = '\n';
+ write(fd, output_buffer, free_pos+1);
return 1;
}
-
+/*
+ * example: 5v'\n'
+ * or: '\n'
+ */
int vci_defense(int fd, char *buffer, player_cards deck)
{
- if(buffer[0] == '\n') /* the player does not want to keep the defense */
+ int last_idx;
+ char *card = NULL;
+
+ if(buffer[0] == '\n') { /* the player does not want to keep the defense */
+ write(fd, buffer, 1);
return 1;
- if(!card_search_by_letter(deck, buffer[0]))
- return 0;
- if(buffer[1] != '\n')
+ }
+ if(buffer[1] != '\n') {
+ printf("incorrect input\n");
return 0;
- return 1;
+ }
+ if((card = card_search_by_letter(deck, buffer[0])) != NULL) {
+ strcpy(output_buffer, card);
+ last_idx = strlen(card);
+ output_buffer[last_idx] = '\n';
+ write(fd, output_buffer, last_idx+1);
+ return 1;
+ }
+ /* card is not found in the deck or cannot be used */
+ return 0;
}
diff --git a/server/card_stack.c b/server/card_stack.c
index aa8af71..c7c18d9 100644
--- a/server/card_stack.c
+++ b/server/card_stack.c
@@ -59,6 +59,15 @@ const char* remove_card_from_stack(player_cards *deck, const char *str)
return 0;
}
+const char* pop_stack(player_cards *deck)
+{
+ struct card_stack_item *tmp;
+
+ tmp = *deck;
+ *deck = (*deck)->next;
+ free(tmp);
+}
+
struct card_stack_item* get_next_card_from_stack(player_cards deck,
player_cards prev)
{
diff --git a/server/card_stack.h b/server/card_stack.h
index d380ded..321cbf0 100644
--- a/server/card_stack.h
+++ b/server/card_stack.h
@@ -17,5 +17,6 @@ const char* remove_card_from_stack(player_cards *deck, const char *str);
struct card_stack_item* get_next_card_from_stack(player_cards deck,
player_cards prev);
int find_card_in_stack(player_cards involved_cards, const char *str);
+const char* pop_stack(player_cards *deck);
#endif
diff --git a/server/server.c b/server/server.c
index 0a2bd0f..b2f1c3b 100644
--- a/server/server.c
+++ b/server/server.c
@@ -7,6 +7,7 @@
#include <fcntl.h>
#include <syslog.h>
#include <time.h>
+#include <netinet/tcp.h>
#include "server.h"
#include "server_data_processing.h"
@@ -34,6 +35,7 @@ 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;
@@ -395,6 +397,8 @@ static void determine_server_state(struct server *serv)
case start_game:
set_state_for_client(serv, attack);
set_whose_turn(serv, attack);
+ update_game_info(serv->gi, serv->connected_players_counter,
+ serv->shuffled_deck_size, serv->position_whose_turn);
set_record_status_for_all(serv);
serv->state = attack_phase_out;
break;
@@ -418,6 +422,7 @@ static void determine_server_state(struct server *serv)
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);
@@ -430,10 +435,18 @@ static void determine_server_state(struct server *serv)
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);
+ update_game_info(serv->gi, serv->connected_players_counter,
+ serv->shuffled_deck_size, serv->position_whose_turn);
serv->state = attack_phase_out;
break;
case defense_phase_out:
@@ -480,7 +493,7 @@ static int accept_new_player(struct server *serv)
}
static void set_up_player_tracking(struct server *serv, fd_set *readfds,
- fd_set *writefds)
+ fd_set *writefds, int *maxfd)
{
int i;
for(i = 0; i < serv->max_sess_arr_size; ++i) {
@@ -489,11 +502,14 @@ static void set_up_player_tracking(struct server *serv, fd_set *readfds,
switch(serv->state) {
case first_player:
- if(serv->sess_arr[i]->record)
+ if(serv->sess_arr[i]->record) {
FD_SET(i, writefds);
+ *maxfd = i > *maxfd ? i : *maxfd;
+ }
break;
case confirmation_waiting:
FD_SET(i, readfds);
+ *maxfd = i > *maxfd ? i : *maxfd;
if(serv->sess_arr[i]->record)
FD_SET(i, writefds);
break;
@@ -502,21 +518,30 @@ static void set_up_player_tracking(struct server *serv, fd_set *readfds,
case table:
case defense_phase_out:
case tossing_phase_out:
- if(serv->sess_arr[i]->record)
+ if(serv->sess_arr[i]->record) {
FD_SET(i, writefds);
+ *maxfd = i > *maxfd ? i : *maxfd;
+ }
break;
case attack_phase_in:
- if(serv->sess_arr[i]->state == attack)
+ if(serv->sess_arr[i]->state == attack) {
FD_SET(i, readfds);
+ *maxfd = i > *maxfd ? i : *maxfd;
+ }
break;
case defense_phase_in:
- if(serv->sess_arr[i]->state == defense)
+ if(serv->sess_arr[i]->state == defense) {
FD_SET(i, readfds);
+ *maxfd = i > *maxfd ? i : *maxfd;
+ }
break;
case tossing_phase_in:
if(serv->sess_arr[i]->state == tossing &&
serv->sess_arr[i]->tm == answer_wait)
+ {
FD_SET(i, readfds);
+ *maxfd = i > *maxfd ? i : *maxfd;
+ }
break;
case no_players:
{}
@@ -646,7 +671,7 @@ int main_loop(struct server *serv)
maxfd = serv->listen_socket;
}
- set_up_player_tracking(serv, &readfds, &writefds);
+ set_up_player_tracking(serv, &readfds, &writefds, &maxfd);
select_result = select(maxfd + 1, &readfds, &writefds, NULL, NULL);
if(select_result == -1)
@@ -677,7 +702,6 @@ static int init_server(struct server *serv, int port)
opt = 1;
setsockopt(serv->listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt,
sizeof(opt));
-
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
diff --git a/server/server.h b/server/server.h
index 46c965b..86e0fca 100644
--- a/server/server.h
+++ b/server/server.h
@@ -7,7 +7,7 @@
enum {
max_buffer_size = 4096,
listen_qlen = 32,
- init_sess_arr_size = 32
+ init_sess_arr_size = 12 /* it was 32 */
};
enum {
diff --git a/server/server_data_processing.c b/server/server_data_processing.c
index 30953bf..b7b2374 100644
--- a/server/server_data_processing.c
+++ b/server/server_data_processing.c
@@ -145,12 +145,12 @@ static void copy_base_info(int *free_pos, struct game_info *gi,
if(gi->cot->card_arr_idx != -1)
copy_cards_on_table(free_pos, *gi->cot);
else
- *free_pos += sprintf(output_buffer + *free_pos, "0:");
+ *free_pos += sprintf(output_buffer + *free_pos, "=:");
if(!is_empty_stack(deck))
copy_own_deck(free_pos, deck);
else
- *free_pos += sprintf(output_buffer + *free_pos, "0:");
+ *free_pos += sprintf(output_buffer + *free_pos, "=:");
}
int print_game_part(const struct session *client, struct game_info *gi)
@@ -186,7 +186,7 @@ int print_game_part(const struct session *client, struct game_info *gi)
gi->position_whose_turn);
/* copying card queue */
if(is_empty_queue(gi->cq))
- free_pos += sprintf(output_buffer + free_pos, "0:");
+ free_pos += sprintf(output_buffer + free_pos, "=:");
else
copy_card_queue(&free_pos, gi->cq);
*(output_buffer + free_pos-1) = '\n';
@@ -207,6 +207,10 @@ static int is_receiving_cards_limit(int total_defense_cards, int total_attack_ca
}
#endif
+
+/*
+ * example: 7v\2#\A^\'\n'
+ */
int get_cards_from_attacker(struct session *client,
const struct cards_on_table *cot,
const player_cards defense_deck,
@@ -219,9 +223,13 @@ int get_cards_from_attacker(struct session *client,
const char *stack_card = NULL;
read_result = read_from_client(client->fd, client->buffer, max_buffer_size);
+ printf("%d\n", read_result);
+ for(i = 0; i < read_result; ++i)
+ putchar(client->buffer[i]);
+ putchar('\n');
if(!read_result)
return read_result;
- for(i = 0, j = 0; i < read_result && client->buffer[i] != '\n'; ++i) {
+ for(i = 0, j = 0; i < read_result; ++i) {
if(client->buffer[i] == '\\') {
given_card[j] = '\0';
j = 0;
@@ -249,6 +257,8 @@ int get_cards_from_attacker(struct session *client,
* 1 - card was bited, not bited, or
* defender didn't want to continue defense phase
*
+ * example: 5v'\n'
+ * or: '\n'
*/
int get_card_from_defender(struct session *client, struct cards_on_table *cot,
const char * trump_suit)
@@ -258,12 +268,16 @@ int get_card_from_defender(struct session *client, struct cards_on_table *cot,
const char *stack_card = NULL;
read_result = read_from_client(client->fd, client->buffer, max_buffer_size);
+ printf("%d\n", read_result);
+ for(i = 0; i < read_result; ++i)
+ putchar(client->buffer[i]);
+ putchar('\n');
if(!read_result)
return read_result;
+ if(client->buffer[0] == '\n')
+ return 1;
for(i = 0; i < read_result && client->buffer[i] != '\n'; ++i)
given_card[i] = client->buffer[i];
- if(given_card[0] == '\n')
- return 1;
given_card[i] = '\0';
if(is_card_bit(cot->card_arr[cot->card_arr_idx-2], given_card, trump_suit)){
stack_card = remove_card_from_stack(&client->deck, given_card);
@@ -280,6 +294,7 @@ int get_card_from_defender(struct session *client, struct cards_on_table *cot,
* 3 - player refused to toss the card
*
* example: 10#\A^\7v\'\n'
+ * or: '\n'
*/
int get_cards_from_tossing_player(struct session *client,
const player_cards defense_deck,
@@ -293,14 +308,15 @@ int get_cards_from_tossing_player(struct session *client,
const char *stack_card = NULL;
read_result = read_from_client(client->fd, client->buffer, max_buffer_size);
+ printf("%d\n", read_result);
+ for(i = 0; i < read_result; ++i)
+ putchar(client->buffer[i]);
+ putchar('\n');
if(!read_result)
return read_result;
for(i = 0, j = 0; i < read_result; ++i) {
if(client->buffer[i] == '\\') {
- /* cancellation */
- if(given_card[0] == '\n')
- return 3;
/* tossing limit was set */
if(client->tm == cancel) {
/* it's impossible to accept cards due to tossing limit */
@@ -326,6 +342,10 @@ 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,
all_cards_received_status ? "all" : "not all");
diff --git a/server/server_game_process.c b/server/server_game_process.c
index 8bf4e60..46a9535 100644
--- a/server/server_game_process.c
+++ b/server/server_game_process.c
@@ -12,7 +12,7 @@ static const char *basic_deck[deck_size] = {
"3#", "4#", "5#", "6#", "7#", "8#", "9#",
"10#", "J#", "Q#", "K#", "A#", "2%", "3%",
"4%", "5%", "6%", "7%", "8%", "9%", "10%",
- "j%", "Q%", "K%", "A%", "2v", "3v", "4v",
+ "J%", "Q%", "K%", "A%", "2v", "3v", "4v",
"5v", "6v", "7v", "8v", "9v", "10v", "Jv",
"Qv", "Kv", "Av"
};
@@ -66,7 +66,7 @@ void deal_cards(const char **shuffled_deck, int *shuffled_cards_left,
for(j = 0; j < card_shortage_quantity; ++j) {
last_idx = *shuffled_cards_left-1;
/* shuffled deck is empty */
- if(last_idx == 0 || last_idx < 0)
+ if(last_idx < 0)
return;
extracted_card = shuffled_deck[last_idx];
push_stack(&turn_queue[i]->deck, extracted_card);
@@ -81,9 +81,10 @@ const char* extract_trump_card(const char **shuffled_deck, int *cards_left)
{
const char *trump_card = NULL;
- trump_card = shuffled_deck[0] ? shuffled_deck[0] : NULL;
+ trump_card = shuffled_deck[*cards_left-1] ?
+ shuffled_deck[*cards_left-1] : NULL;
if(trump_card) {
- shuffled_deck[0] = NULL;
+ shuffled_deck[*cards_left-1] = NULL;
--*cards_left;
}
return trump_card;
@@ -226,6 +227,56 @@ int is_card_bit(const char *attack_card, const char *defend_card,
return 1;
return 0;
}
+
+static void find_out_trump_cards_in_deck(player_cards *trump_cards,
+ player_cards deck,
+ const char *trump_suit)
+{
+ const char *suit = NULL, *card = NULL;
+
+ while(deck) {
+ card = deck->str;
+ suit= card + strlen(card) - 1;
+ if(*suit == *trump_suit)
+ push_stack(trump_cards, card);
+ deck = deck->next;
+ }
+}
+
+static int is_same_suit_and_not_meet(player_cards involved_cards,
+ struct card_stack_item *defend_card,
+ struct card_queue_item *attack_card)
+
+{
+ int length;
+ const char *attack_suit, *defend_suit;
+
+ if(!find_card_in_stack(involved_cards, defend_card->str)) {
+ length = strlen(attack_card->str);
+ attack_suit= attack_card->str + length - 1;
+ length = strlen(defend_card->str);
+ defend_suit = defend_card->str + length - 1;
+ return *attack_suit == *defend_suit;
+ }
+ return 0;
+}
+
+static int trump_cards_left_uncovered(player_cards remaining_cards,
+ const char *trump_suit)
+{
+ const char *suit;
+ const char *card = NULL;
+
+ while(remaining_cards) {
+ card = remaining_cards->str;
+ suit = card + strlen(card) - 1;
+ if(*suit == *trump_suit)
+ return 1;
+ remaining_cards = remaining_cards->next;
+ }
+ return 0;
+}
+
/*
* analyze that each attacker card can be beat
* TODO: free memory
@@ -233,13 +284,18 @@ int is_card_bit(const char *attack_card, const char *defend_card,
int check_defender_can_defend(struct card_queue *cq,
player_cards deck, const char *trump_suit)
{
- int is_bited_card;
+ int current_rank = 0, min_rank = 0;
struct card_stack_item *next_defend_card;
struct card_queue_item *next_attack_card;
- player_cards involved_cards;
+ const char* card_with_min_rank = NULL;
+
+ player_cards involved_cards, trump_cards, remaining_attack_cards;
- is_bited_card = 0;
init_stack(&involved_cards);
+ init_stack(&trump_cards);
+ init_stack(&remaining_attack_cards);
+
+ find_out_trump_cards_in_deck(&trump_cards, deck, trump_suit);
next_attack_card = NULL;
while((next_attack_card = get_next_card_from_queue(cq, next_attack_card))) {
@@ -247,23 +303,47 @@ int check_defender_can_defend(struct card_queue *cq,
next_defend_card = NULL;
next_defend_card = get_next_card_from_stack(deck, next_defend_card);
- /* stack traversal */
+ card_with_min_rank = NULL;
+ min_rank = 0;
+
while(next_defend_card) {
if(is_card_bit(next_attack_card->str, next_defend_card->str,
trump_suit))
- /* if card doesn't meet */
- if(!find_card_in_stack(involved_cards, next_defend_card->str)) {
- push_stack(&involved_cards, next_defend_card->str);
- is_bited_card = 1;
- break;
+ {
+ if(is_same_suit_and_not_meet(involved_cards, next_defend_card,
+ next_attack_card))
+ {
+ current_rank = convert_rank_to_int(next_defend_card->str);
+ if(!card_with_min_rank || min_rank > current_rank) {
+ card_with_min_rank = next_defend_card->str;
+ min_rank = current_rank;
+ }
}
- get_next_card_from_stack(deck, next_defend_card);
+ }
+ next_defend_card = get_next_card_from_stack(deck, next_defend_card);
}
- if(is_bited_card)
- is_bited_card = 0;
- else
- return 0;
+ if(card_with_min_rank) {
+ push_stack(&involved_cards, card_with_min_rank);
+ if(find_card_in_stack(trump_cards, card_with_min_rank))
+ remove_card_from_stack(&trump_cards, card_with_min_rank);
+ } else
+ push_stack(&remaining_attack_cards, next_attack_card->str);
}
+ /*
+ * there are trump attacking uncovered cards remaining
+ * if the defender also has trump cards, they are of a lower rank
+ */
+ if(trump_cards_left_uncovered(remaining_attack_cards, trump_suit))
+ return 0;
+ while(remaining_attack_cards) {
+ if(!is_empty_stack(trump_cards)) {
+ pop_stack(&trump_cards);
+ pop_stack(&remaining_attack_cards);
+ } else
+ break;
+ }
+ if(!is_empty_stack(remaining_attack_cards))
+ return 0;
return 1;
}
@@ -473,3 +553,8 @@ int is_receiving_cards_limit(const struct cards_on_table *cot,
return 1;
return 0;
}
+
+void clear_defense_lost_status(struct session *defender)
+{
+ defender->defense_lost = 0;
+}
diff --git a/server/server_game_process.h b/server/server_game_process.h
index 8891a56..9338c25 100644
--- a/server/server_game_process.h
+++ b/server/server_game_process.h
@@ -75,4 +75,6 @@ int check_all_answers_were_received(const struct session **turn_queue,
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);
+
#endif