back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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