back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
path: root/server/server_game_process.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/server_game_process.c')
-rw-r--r--server/server_game_process.c475
1 files changed, 475 insertions, 0 deletions
diff --git a/server/server_game_process.c b/server/server_game_process.c
new file mode 100644
index 0000000..8bf4e60
--- /dev/null
+++ b/server/server_game_process.c
@@ -0,0 +1,475 @@
+#include "server_game_process.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+enum { deck_size = 52 };
+
+static const char *basic_deck[deck_size] = {
+ "2^", "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#", "2%", "3%",
+ "4%", "5%", "6%", "7%", "8%", "9%", "10%",
+ "j%", "Q%", "K%", "A%", "2v", "3v", "4v",
+ "5v", "6v", "7v", "8v", "9v", "10v", "Jv",
+ "Qv", "Kv", "Av"
+};
+
+static int get_random_idx()
+{
+ return 0 + (int)((double)deck_size*rand()/(RAND_MAX + 1.0));
+}
+
+const char** get_shuffled_deck()
+{
+ int i, new_idx;
+ const char **shuffled_deck = calloc(deck_size, sizeof(char*));
+ for(i = 0; i < deck_size; ++i) {
+ new_idx = get_random_idx();
+ while(shuffled_deck[new_idx])
+ new_idx = get_random_idx();
+ shuffled_deck[new_idx] = basic_deck[i];
+ }
+ return shuffled_deck;
+}
+
+void deal_first_cards(const char **shuffled_deck, int *cards_left,
+ player_cards *deck)
+{
+ int i, last_idx;
+ const char *str;
+ for(i = 0; i < start_deck_size; ++i) {
+ last_idx = *cards_left-1;
+ str = shuffled_deck[last_idx];
+ if(str) {
+ push_stack(deck, str);
+ --*cards_left;
+ shuffled_deck[last_idx] = NULL;
+ }
+ }
+}
+
+void deal_cards(const char **shuffled_deck, int *shuffled_cards_left,
+ struct session **turn_queue, int players_number,
+ int *card_quantity_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) {
+ key = turn_queue[i]->player_position - 1;
+ player_deck_size = card_quantity_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) {
+ last_idx = *shuffled_cards_left-1;
+ /* shuffled deck is empty */
+ if(last_idx == 0 || 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;
+
+ trump_card = shuffled_deck[0] ? shuffled_deck[0] : NULL;
+ if(trump_card) {
+ shuffled_deck[0] = NULL;
+ --*cards_left;
+ }
+ return trump_card;
+}
+#if 0
+const char* find_trump_suit(const char **shuffled_deck, int *cards_left)
+{
+ const char *trump_suit = NULL;
+ trump_suit = shuffled_deck[0] ? shuffled_deck[0] : NULL;
+ if(trump_suit) {
+ shuffled_deck[0] = NULL;
+ trump_suit += strlen(trump_suit) - 1;
+ --*cards_left;
+ }
+ return trump_suit;
+}
+#endif
+
+int convert_rank_to_int(const char *card)
+{
+ int length;
+ char str_rank[2];
+
+ length = strlen(card);
+ /* 10 - the only one of its kind */
+ if(length == 3)
+ return 10;
+
+ str_rank[0] = card[0];
+ str_rank[1] = '\0';
+
+ switch(card[0]) {
+ case 'J':
+ return 11;
+ case 'Q':
+ return 12;
+ case 'K':
+ return 13;
+ case 'A':
+ return 14;
+ default:
+ return strtol(str_rank, NULL, 10);
+ }
+ return 0;
+}
+
+int find_lowest_trump(player_cards deck, const char *trump_suit)
+{
+ int length, lowest_rank = 0, current_rank;
+ const char *suit = NULL;
+
+ while(deck) {
+ length = strlen(deck->str);
+ suit = deck->str + length - 1;
+ if(*suit == *trump_suit) {
+ current_rank = convert_rank_to_int(deck->str);
+ if(!lowest_rank || lowest_rank > current_rank)
+ lowest_rank = current_rank;
+ }
+ deck = deck->next;
+ }
+ return lowest_rank;
+}
+
+void shift_turn_queue_by_one(struct session **turn_queue, int size)
+{
+ int i;
+ struct session *tmp = turn_queue[0];
+ for(i = 1; i < 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)
+{
+ int i;
+
+ for(i = 0; i < 2; ++i)
+ shift_turn_queue_by_one(turn_queue, size);
+}
+
+void update_card_quantity_arr(struct server *serv)
+{
+ int i, player_position_idx;
+
+ 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);
+ }
+}
+
+struct game_info* get_new_game_info(int players_number, int *card_quantity_arr,
+ int shuffled_cards_left,
+ const char *trump_card,
+ int position_whose_turn,
+ struct card_queue *cq,
+ struct cards_on_table *cot)
+
+{
+ struct game_info *gi = malloc(sizeof(struct game_info));
+ gi->players_number = players_number;
+ gi->card_quantity_arr = card_quantity_arr;
+ gi->shuffled_cards_left = shuffled_cards_left;
+ gi->trump_card = trump_card;
+ gi->position_whose_turn = position_whose_turn;
+ gi->cq = cq;
+ gi->cot = cot;
+ return gi;
+}
+
+void update_game_info(struct game_info *gi, int players_number,
+ int shuffled_cards_left, int position_whose_turn)
+{
+ gi->players_number = players_number;
+ gi->shuffled_cards_left = shuffled_cards_left;
+ gi->position_whose_turn = position_whose_turn;
+}
+
+int is_card_bit(const char *attack_card, const char *defend_card,
+ const char *trump_suit)
+{
+ int length, attack_rank, defend_rank;
+ const char *attack_suit, *defend_suit;
+
+ length = strlen(attack_card);
+ attack_suit= attack_card + length - 1;
+ length = strlen(defend_card);
+ defend_suit = defend_card + length - 1;
+
+ /* suits matched */
+ if(!strcmp(attack_suit, defend_suit)) {
+ attack_rank = convert_rank_to_int(attack_card);
+ defend_rank = convert_rank_to_int(defend_card);
+ if(defend_rank > attack_rank)
+ return 1;
+ /* defender has a trump suit */
+ } else if(!strcmp(defend_suit, trump_suit))
+ return 1;
+ return 0;
+}
+/*
+ * analyze that each attacker card can be beat
+ * TODO: free memory
+ */
+int check_defender_can_defend(struct card_queue *cq,
+ player_cards deck, const char *trump_suit)
+{
+ int is_bited_card;
+ struct card_stack_item *next_defend_card;
+ struct card_queue_item *next_attack_card;
+ player_cards involved_cards;
+
+ is_bited_card = 0;
+ init_stack(&involved_cards);
+
+ next_attack_card = NULL;
+ while((next_attack_card = get_next_card_from_queue(cq, next_attack_card))) {
+ /* get first defend card */
+ next_defend_card = NULL;
+ next_defend_card = get_next_card_from_stack(deck, next_defend_card);
+
+ /* stack traversal */
+ 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;
+ }
+ get_next_card_from_stack(deck, next_defend_card);
+ }
+ if(is_bited_card)
+ is_bited_card = 0;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+static int check_matched_ranks(const char *attack_card,
+ const char *not_defender_card)
+{
+ int attack_rank, not_defender_rank;
+
+ attack_rank = convert_rank_to_int(attack_card);
+ not_defender_rank = convert_rank_to_int(not_defender_card);
+ return attack_rank == not_defender_rank;
+}
+
+int check_someone_can_toss_card(struct session **turn_queue,
+ int players_quantity,
+ struct card_queue *cq,
+ struct cards_on_table *cot)
+{
+ int i, j;
+ struct card_queue_item *attack_card_in_queue;
+ struct card_stack_item *not_defender_card;
+
+ for(i = 0; i < players_quantity; ++i) {
+ /* skipping defender's cards */
+ if(i == 1)
+ continue;
+
+ /* checking card queue of attack cards */
+ attack_card_in_queue = NULL;
+ while((attack_card_in_queue =
+ get_next_card_from_queue(cq, attack_card_in_queue))) {
+ not_defender_card = NULL;
+ while((not_defender_card =
+ get_next_card_from_stack(turn_queue[i]->deck,
+ not_defender_card)) &&
+ !check_matched_ranks(attack_card_in_queue->str,
+ not_defender_card->str))
+ {}
+ if(not_defender_card)
+ return 1;
+ }
+ /* checking cards on table */
+ for(j = cot->card_arr_idx; j >= 0; --j) {
+ if(cot->card_arr[j][0] == '-' || cot->card_arr[j][0] == '\\')
+ continue;
+ not_defender_card = NULL;
+ while((not_defender_card =
+ get_next_card_from_stack(turn_queue[i]->deck,
+ not_defender_card)) &&
+ !check_matched_ranks(cot->card_arr[j],
+ not_defender_card->str))
+ {}
+ if(not_defender_card)
+ return 1;
+ }
+ }
+ return 0;
+}
+/* is used to make the client's state tossing */
+int check_player_can_toss_card(player_cards deck, struct cards_on_table *cot)
+{
+ int i;
+ struct card_stack_item *not_defender_card;
+
+ /* checking cards on table */
+ for(i = cot->card_arr_idx; i >= 0; --i) {
+ if(cot->card_arr[i][0] == '-' || cot->card_arr[i][0] == '\\')
+ continue;
+ not_defender_card = NULL;
+ while((not_defender_card =
+ get_next_card_from_stack(deck, not_defender_card)) &&
+ !check_matched_ranks(cot->card_arr[i], not_defender_card->str))
+ {}
+ if(not_defender_card)
+ return 1;
+ }
+ return 0;
+}
+
+int is_correct_tossing_card(const char *card, struct cards_on_table *cot)
+{
+ int i;
+
+ for(i = cot->card_arr_idx; i >= 0; --i) {
+ if(cot->card_arr[i][0] == '-' || cot->card_arr[i][0] == '\\')
+ continue;
+ if(check_matched_ranks(cot->card_arr[i], card))
+ return 1;
+ }
+ return 0;
+}
+
+/* when defender cannot bit any card */
+void put_all_cards_from_queue_to_table(struct cards_on_table *cot,
+ struct card_queue *cq)
+{
+ const char *card;
+
+ while(!is_empty_queue(cq)) {
+ card = pop_card_queue(cq);
+ ++cot->card_arr_idx;
+ cot->card_arr[cot->card_arr_idx] = card;
+ ++cot->card_arr_idx;
+ cot->card_arr[cot->card_arr_idx] = "\\";
+ ++cot->card_arr_idx;
+ cot->card_arr[cot->card_arr_idx] = "-";
+ }
+}
+
+void put_one_card_from_queue_to_table(struct cards_on_table *cot,
+ struct card_queue *cq)
+{
+ const char *card;
+
+ card = pop_card_queue(cq);
+ ++cot->card_arr_idx;
+ cot->card_arr[cot->card_arr_idx] = card;
+ ++cot->card_arr_idx;
+ cot->card_arr[cot->card_arr_idx] = "\\";
+ ++cot->card_arr_idx;
+ cot->card_arr[cot->card_arr_idx] = "-";
+}
+
+/* it used by defender to bit attack card */
+void put_defender_card_on_table(struct cards_on_table *cot, const char *card)
+{
+ cot->card_arr[cot->card_arr_idx] = card;
+}
+
+void move_all_cards_to_defender(struct cards_on_table *cot, player_cards *deck)
+{
+ int i;
+#if 0
+ const char *card;
+
+ while(!is_empty_queue(cq)) {
+ card = pop_card_queue(cq);
+ push_stack(deck, card);
+ }
+#endif
+ for(i = cot->card_arr_idx; i >= 0; --i) {
+ if(cot->card_arr[i][0] == '-' || cot->card_arr[i][0] == '\\')
+ continue;
+ push_stack(deck, cot->card_arr[i]);
+ }
+ cot->card_arr_idx = i;
+}
+
+void remove_cards_from_table(struct cards_on_table *cot)
+{
+ cot->card_arr_idx = -1;
+}
+
+int calculate_defense_card_quantity_on_table(const struct cards_on_table *cot)
+{
+ int i, counter = 0;
+
+ for(i = 0; i <= cot->card_arr_idx; ++i) {
+ /* every 3 position meets a defender card */
+ if(!((i+1) % 3)) {
+ if(!strcmp(cot->card_arr[i], "-"))
+ continue;
+ else
+ ++counter;
+ }
+ }
+ return counter;
+}
+
+int calculate_attack_card_quantity_on_table(const struct cards_on_table *cot)
+{
+ int i, counter = 0;
+
+ for(i = 0; i <= cot->card_arr_idx; ++i)
+ if(i == 0 || !(i % 3))
+ ++counter;
+ return counter;
+}
+
+int check_all_answers_were_received(const struct session **turn_queue, int size)
+{
+ int i;
+
+ for(i = 0; i < size; ++i)
+ if(turn_queue[i]->tm == answer_wait)
+ return 0;
+ return 1;
+}
+
+int is_receiving_cards_limit(const struct cards_on_table *cot,
+ player_cards defense_deck,
+ const struct card_queue *cq)
+{
+ int total_defense_cards, total_attack_cards;
+
+ total_defense_cards = calculate_defense_card_quantity_on_table(cot);
+ total_attack_cards = calculate_attack_card_quantity_on_table(cot);
+ total_defense_cards +=
+ find_out_card_quantity_in_deck(defense_deck);
+ total_attack_cards +=
+ find_out_card_quantity_in_cq(cq);
+
+ if(total_defense_cards >= start_deck_size &&
+ total_attack_cards == start_deck_size) {
+ return 1;
+ } else if(total_defense_cards == total_attack_cards)
+ return 1;
+ return 0;
+}