/** * This is a base to make up randomised decks of cards. * @author Pinkfish * @started Thu Dec 7 07:34:10 PST 2000 */ #include <room/card_base.h> #define CARD_NUM_MAX CARD_NUMBER_KING int is_card_red(class playing_card card); class playing_card* make_deck(int number_of_decks, int number_of_jokers) { class playing_card* deck; class playing_card card; int i; int suit; int num; deck = ({ }); for (i = 0; i < number_of_decks; i++) { for (suit = CARD_SUIT_HEARTS; suit <= CARD_SUIT_SPADES; suit++) { for (num = 1; num <= CARD_NUM_MAX; num++) { card = new(class playing_card); card->suit = suit; card->number = num; deck += ({ card }); } } } for (i = 0; i < number_of_jokers; i++) { card = new(class playing_card); card->suit = CARD_SUIT_JOKER; deck += ({ card }); } return deck; } /* make_deck() */ /** * This method scrabled the deck and shuffles it. * @param deck the deck to shuffle * @return a shuffled deck */ class playing_card* shuffle_deck(class playing_card* deck) { class playing_card* new_deck; int pos; int i; for (i = 0; i < 2; i++) { new_deck = ({ }); while (sizeof(deck)) { pos = random(sizeof(deck)); new_deck += deck[pos..pos]; deck = deck[0..pos - 1] + deck[pos+1..]; } deck = new_deck; } return deck; } /* shuffle_deck() */ /** * This method returns the suit letter associated with the card. * @param suit the suit to get the letter of * @return the letter of the suit */ string query_suit_letter(int suit) { switch (suit) { case CARD_SUIT_SPADES : return "S"; break; case CARD_SUIT_HEARTS : return "H"; break; case CARD_SUIT_DIAMONDS : return "D"; break; case CARD_SUIT_CLUBS : return "C"; break; case CARD_SUIT_JOKER : return "J"; } } /* query_suit_letter() */ /** * This method returns the three character string for the card. * @return the three character string for the card */ string query_card_string(class playing_card card) { string ret; string colour; if (card->suit == CARD_SUIT_JOKER) { return "*J*"; } ret = query_suit_letter(card->suit) + "%^RESET%^"; if (is_card_red(card)) { colour = "%^BOLD%^%^RED%^"; } else { colour = "%^BOLD%^"; } if (card->number > 10 || card->number == CARD_NUMBER_ACE) { switch (card->number) { case CARD_NUMBER_JACK : ret = colour + "J " + ret; break; case CARD_NUMBER_QUEEN : ret = colour + "Q " + ret; break; case CARD_NUMBER_KING : ret = colour + "K " + ret; break; case CARD_NUMBER_ACE : ret = colour + "A " + ret; break; } } else { ret = sprintf("%s%-2d%s", colour, card->number, ret); } return ret + "%^RESET%^"; } /* query_card_string() */ /** * This method determines if the card colour is red. * @param card the card to check * @return 1 if it is, 0 if not */ int is_card_red(class playing_card card) { return card->suit == CARD_SUIT_HEARTS || card->suit == CARD_SUIT_DIAMONDS; } /* is_card_red() */ /** * This method determines if the card colour is black. * @param card the card to check * @return 1 if it is, 0 if not */ int is_card_black(class playing_card card) { return card->suit == CARD_SUIT_SPADES || card->suit == CARD_SUIT_CLUBS; } /* is_card_black() */ /** * This method checks to see if the card is a joker. * @param card the card to check * @return 1 if it is, 0 if not */ int is_card_joker(class playing_card card) { return card->suit == CARD_SUIT_JOKER; } /* is_card_joker() */ /** * This method makes a array for a 3x3 card. * @param card the card to make 3x3 * @return the three line array */ string* query_card_three(class playing_card card) { string* lines; if (is_card_red(card)) { lines = allocate(3, "%^BOLD%^%^RED%^"); } else { lines = allocate(3, "%^BOLD%^"); } switch (card->suit) { case CARD_SUIT_HEARTS : lines[0] += "H %^RESET%^"; lines[2] += " H%^RESET%^"; break; case CARD_SUIT_DIAMONDS : lines[0] += "D %^RESET%^"; lines[2] += " D%^RESET%^"; break; case CARD_SUIT_CLUBS : lines[0] += "C %^RESET%^"; lines[2] += " C%^RESET%^"; break; case CARD_SUIT_SPADES : lines[0] += "S %^RESET%^"; lines[2] += " S%^RESET%^"; break; case CARD_SUIT_JOKER : lines[0] += "J *%^RESET%^"; lines[1] += " O %^RESET%^"; lines[2] += "* K%^RESET%^"; return lines; } if (card->number <= 10 && card->number != CARD_NUMBER_ACE) { if (card->number == 10) { lines[1] += " 10%^RESET%^"; } else { lines[1] += " " + card->number + " %^RESET%^"; } } else { switch (card->number) { case CARD_NUMBER_KING : lines[1] += " K %^RESET%^"; break; case CARD_NUMBER_QUEEN : lines[1] += " Q %^RESET%^"; break; case CARD_NUMBER_JACK : lines[1] += " J %^RESET%^"; break; case CARD_NUMBER_ACE : lines[1] += " A %^RESET%^"; break; } } return lines; } /* query_card_three() */ /** * This method makes a array for a 2x2 card. * @param card the card to make 2x2 * @return the two line array */ string* query_card_two(class playing_card card) { string* lines; lines = allocate(2); switch (card->suit) { case CARD_SUIT_HEARTS : lines[0] = "H "; break; case CARD_SUIT_DIAMONDS : lines[0] = "D "; break; case CARD_SUIT_CLUBS : lines[0] = "C "; break; case CARD_SUIT_SPADES : lines[0] = "S "; break; case CARD_SUIT_JOKER : lines[0] = "J*"; lines[1] = "*O"; return lines; } if (card->number <= 10 && card->number != CARD_NUMBER_ACE) { lines[1] = sprintf("%2d", card->number); } else { switch (card->number) { case CARD_NUMBER_KING : lines[1] = " K"; break; case CARD_NUMBER_QUEEN : lines[1] = " Q"; break; case CARD_NUMBER_JACK : lines[1] = " J"; break; case CARD_NUMBER_ACE : lines[1] = " A"; break; } } return lines; } /* query_card_three() */ /** * This method returns a string showing the hand. * @param hand the hand to show * @param three 1 for a 3x3, 0 for a 2x2 * @return a string representation of the hand */ string query_hand_string(class playing_card* hand, int flags, int cols) { string hand_str; int i; int j; int width; int start_pos; string top; string line; string start; string end; string start_space; string end_space; mixed card_str; if (!sizeof(hand)) { return "No cards\n"; } hand_str = ""; if (!(flags & CARD_HAND_NO_ADORNMENTS)) { if (flags & CARD_HAND_THREE || flags & CARD_HAND_SINGLE) { top = "+---+"; width = 5; } else { top = "+--+"; width = 4; } start = "|"; end = "|"; start_space = " "; end_space = " "; } else { top = 0; line = ""; start = " "; end = " "; start_space = " "; end_space = " "; if (flags & CARD_HAND_THREE || flags & CARD_HAND_SINGLE) { width = 3; } else { width = 2; } } start_pos = 0; if (flags & CARD_HAND_THREE) { card_str = map(hand, (: query_card_three :)); } else if (flags & CARD_HAND_SINGLE) { card_str = map(hand, (: ({ query_card_string($1) }) :)); } else { card_str = map(hand, (: query_card_two :)); } while (start_pos < sizeof(hand)) { if (top) { // // Make the top of the card. // line = ""; for (i = 0; i + start_pos < sizeof(hand) && (i + 1) * width < cols; i++) { line += top; } line += "\n"; } if (flags & CARD_HAND_LETTERS) { for (i = 0; i + start_pos < sizeof(hand) && (i + 1) * width < cols; i++) { if (flags & CARD_HAND_THREE) { hand_str += start_space + sprintf(" %c ", 'A' + i + start_pos) + end_space; } else { hand_str += start_space + sprintf("%c ", 'A' + i + start_pos) + end_space; } } } hand_str += "\n" + line; for (j = 0; j < sizeof(card_str[0]); j++) { for (i = 0; i + start_pos < sizeof(card_str) && (i + 1) * width < cols; i++) { hand_str += start + (card_str[i + start_pos][j]) + end; } hand_str += "\n"; } hand_str += line; start_pos += cols / width; } return hand_str; } /* query_hand_string() */ private int compare_cards(class playing_card card1, class playing_card card2, int flags) { if (card1->suit == card2->suit || (flags & 2)) { if (!(flags & 1)) { return card1->number - card2->number; } if (card1->number == CARD_NUMBER_ACE) { return 1; } if (card2->number == CARD_NUMBER_ACE) { return -1; } return card1->number - card2->number; } return card1->suit - card2->suit; } /* compare_cards() */ /** * This method sorts the cards into useful clumps. * @param deck the deck to sort * @param flags 1 = ace high, 2 = only numbers * @return the sorted deck */ class playing_card* sort_cards(class playing_card* deck, int flags) { return sort_array(deck, (: compare_cards($1, $2, $(flags)) :)); } /* sort_cards() */