2010-04-11 20:11:45 +00:00
|
|
|
#include <stdio.h>
|
2010-04-03 07:11:27 +00:00
|
|
|
#include <ncurses.h>
|
|
|
|
#include <malloc.h>
|
|
|
|
#include <string.h>
|
2010-04-03 18:26:21 +00:00
|
|
|
#include <locale.h>
|
2010-04-07 01:52:00 +00:00
|
|
|
#include "deck.h"
|
2010-04-03 07:11:27 +00:00
|
|
|
#include "display.h"
|
|
|
|
|
2010-04-12 05:56:28 +00:00
|
|
|
void initialize_curses() {
|
2010-04-03 18:26:21 +00:00
|
|
|
setlocale(LC_ALL, ""); /* supporting unicode characters */
|
|
|
|
initscr(); /* initialize the terminal in curses mode */
|
|
|
|
raw(); /* disable line buffers */
|
|
|
|
noecho(); /* character echo is unnecessary */
|
|
|
|
keypad(stdscr, TRUE); /* enable F and arrow keys */
|
2010-04-11 21:08:11 +00:00
|
|
|
start_color(); /* I want colors */
|
2010-04-12 05:56:28 +00:00
|
|
|
curs_set(FALSE); /* invisible cursor */
|
2010-04-03 19:34:45 +00:00
|
|
|
|
|
|
|
init_pair(1, COLOR_BLACK, COLOR_WHITE);
|
|
|
|
init_pair(2, COLOR_RED, COLOR_WHITE);
|
|
|
|
init_pair(3, COLOR_WHITE, COLOR_BLUE);
|
2010-04-12 05:56:28 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void end_curses() {
|
|
|
|
endwin();
|
|
|
|
puts("Game finished.");
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void initialize_game() {
|
|
|
|
struct deck *deck = NULL;
|
|
|
|
int pressed_key;
|
|
|
|
|
|
|
|
mvprintw(11, 27, "Welcome to tty-solitaire.");
|
|
|
|
mvprintw(12, 19, "Press the space bar to play or q to quit.");
|
|
|
|
while (1) {
|
|
|
|
switch (pressed_key = getch()) {
|
|
|
|
case KEY_SPACEBAR:
|
|
|
|
clear();
|
|
|
|
refresh();
|
|
|
|
assume_default_colors(COLOR_WHITE, COLOR_GREEN);
|
|
|
|
draw_empty_stacks();
|
|
|
|
allocate_deck(&deck);
|
|
|
|
initialize_deck(deck);
|
|
|
|
set_deck_stacks_coordinates(deck);
|
|
|
|
fill_deck(deck);
|
|
|
|
shuffle_deck(deck);
|
|
|
|
deal_cards(deck);
|
|
|
|
draw_game(deck);
|
|
|
|
getchar();
|
|
|
|
end_curses();
|
|
|
|
end_game(deck);
|
|
|
|
return;
|
|
|
|
case 'q':
|
|
|
|
case 'Q':
|
|
|
|
end_curses();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void end_game(struct deck *deck) {
|
|
|
|
delete_deck(deck);
|
|
|
|
|
|
|
|
return;
|
2010-04-03 18:26:21 +00:00
|
|
|
}
|
|
|
|
|
2010-04-05 01:48:55 +00:00
|
|
|
void draw_empty_stacks() {
|
|
|
|
WINDOW **empty_stack;
|
|
|
|
|
|
|
|
empty_stack = malloc(EMPTY_STACKS_NUMBER * sizeof(**empty_stack));
|
|
|
|
|
|
|
|
empty_stack[0] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 1, 1);
|
|
|
|
empty_stack[1] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 1, 9);
|
|
|
|
empty_stack[2] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 1, 25);
|
|
|
|
empty_stack[3] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 1, 33);
|
|
|
|
empty_stack[4] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 1, 41);
|
|
|
|
empty_stack[5] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 1, 49);
|
|
|
|
empty_stack[6] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 7, 1);
|
|
|
|
empty_stack[7] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 7, 9);
|
|
|
|
empty_stack[8] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 7, 17);
|
|
|
|
empty_stack[9] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 7, 25);
|
|
|
|
empty_stack[10] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 7, 33);
|
|
|
|
empty_stack[11] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 7, 41);
|
|
|
|
empty_stack[12] = newwin(FRAME_HEIGHT, FRAME_WIDTH, 7, 49);
|
|
|
|
|
|
|
|
for (int i = 0; i < EMPTY_STACKS_NUMBER; i++) {
|
|
|
|
box(empty_stack[i], 0, 0);
|
|
|
|
wrefresh(empty_stack[i]);
|
2010-04-05 01:54:07 +00:00
|
|
|
delwin(empty_stack[i]);
|
2010-04-05 01:48:55 +00:00
|
|
|
}
|
|
|
|
|
2010-04-07 00:59:21 +00:00
|
|
|
free(empty_stack);
|
|
|
|
|
2010-04-05 01:48:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-04-03 07:11:27 +00:00
|
|
|
char *card_suit(enum suit suit) {
|
|
|
|
char *card_suit;
|
|
|
|
|
2010-04-05 00:00:36 +00:00
|
|
|
card_suit = malloc(5 * sizeof(*card_suit));
|
2010-04-03 07:11:27 +00:00
|
|
|
|
|
|
|
switch(suit) {
|
2010-04-03 18:24:10 +00:00
|
|
|
case DIAMONDS: strcpy(card_suit, DIAMONDS_SYMBOL); break;
|
|
|
|
case SPADES: strcpy(card_suit, SPADES_SYMBOL); break;
|
|
|
|
case HEARTS: strcpy(card_suit, HEARTS_SYMBOL); break;
|
|
|
|
case CLUBS: strcpy(card_suit, CLUBS_SYMBOL); break;
|
2010-04-03 07:11:27 +00:00
|
|
|
default: strcpy(card_suit, "?");
|
|
|
|
}
|
|
|
|
|
|
|
|
return(card_suit);
|
|
|
|
}
|
2010-04-03 18:49:57 +00:00
|
|
|
|
|
|
|
char *card_value(enum value value) {
|
|
|
|
char *card_value;
|
|
|
|
|
2010-04-05 00:00:36 +00:00
|
|
|
card_value = malloc(2 * sizeof(*card_value));
|
2010-04-03 18:49:57 +00:00
|
|
|
|
|
|
|
switch(value) {
|
|
|
|
case TWO: card_value = "2"; break;
|
|
|
|
case THREE: card_value = "3"; break;
|
|
|
|
case FOUR: card_value = "4"; break;
|
|
|
|
case FIVE: card_value = "5"; break;
|
|
|
|
case SIX: card_value = "6"; break;
|
|
|
|
case SEVEN: card_value = "7"; break;
|
|
|
|
case EIGHT: card_value = "8"; break;
|
|
|
|
case NINE: card_value = "9"; break;
|
|
|
|
case TEN: card_value = "10"; break;
|
|
|
|
case JACK: card_value = "J"; break;
|
|
|
|
case QUEEN: card_value = "Q"; break;
|
|
|
|
case KING: card_value = "K"; break;
|
|
|
|
case ACE: card_value = "A"; break;
|
|
|
|
default: card_value = "?";
|
|
|
|
}
|
|
|
|
|
|
|
|
return(card_value);
|
|
|
|
}
|
2010-04-03 19:34:45 +00:00
|
|
|
|
|
|
|
void draw_value(struct card *card) {
|
|
|
|
mvwprintw(card->frame->shape, 0, 0, card_value(card->value));
|
2010-04-11 23:11:40 +00:00
|
|
|
mvwprintw(card->frame->shape, 4,
|
|
|
|
6 - (strlen(card_value(card->value)) - 1), card_value(card->value));
|
2010-04-03 19:34:45 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void draw_suit(struct card *card) {
|
|
|
|
if (card->suit % 2 == 0) {
|
|
|
|
wattron(card->frame->shape, COLOR_PAIR(RED_ON_WHITE));
|
|
|
|
} else {
|
|
|
|
wattron(card->frame->shape, COLOR_PAIR(BLACK_ON_WHITE));
|
2010-04-11 23:11:40 +00:00
|
|
|
}
|
|
|
|
mvwprintw(card->frame->shape, 0, 1 + (strlen(card_value(card->value) + 1)),
|
|
|
|
card_suit(card->suit));
|
|
|
|
mvwprintw(card->frame->shape, 4, 5 - (strlen(card_value(card->value) + 1)),
|
|
|
|
card_suit(card->suit));
|
|
|
|
if (card->suit % 2 == 0) {
|
|
|
|
wattroff(card->frame->shape, COLOR_PAIR(RED_ON_WHITE));
|
|
|
|
} else {
|
2010-04-03 19:34:45 +00:00
|
|
|
wattroff(card->frame->shape, COLOR_PAIR(BLACK_ON_WHITE));
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void draw_front(struct card *card) {
|
|
|
|
wbkgd(card->frame->shape, COLOR_PAIR(BLACK_ON_WHITE));
|
|
|
|
draw_value(card);
|
|
|
|
draw_suit(card);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void draw_back(struct card *card) {
|
|
|
|
wbkgd(card->frame->shape, COLOR_PAIR(WHITE_ON_BLUE));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void draw_card(struct card *card) {
|
2010-04-11 20:11:45 +00:00
|
|
|
mvwin(card->frame->shape, card->frame->start_y, card->frame->start_x);
|
2010-04-03 19:34:45 +00:00
|
|
|
if (card->face == EXPOSED) {
|
|
|
|
draw_front(card);
|
|
|
|
} else {
|
|
|
|
draw_back(card);
|
|
|
|
}
|
2010-04-11 20:11:45 +00:00
|
|
|
wrefresh(card->frame->shape);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void draw_stack(struct stack *stack) {
|
|
|
|
if (!empty(stack)) {
|
2010-04-11 22:43:41 +00:00
|
|
|
struct stack *iterator = stack->next;
|
2010-04-11 20:11:45 +00:00
|
|
|
while (iterator != NULL) {
|
|
|
|
draw_card(iterator->card);
|
|
|
|
iterator = iterator->next;
|
|
|
|
}
|
2010-04-11 22:43:41 +00:00
|
|
|
draw_card(stack->card);
|
2010-04-11 20:11:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void draw_game(struct deck *deck) {
|
|
|
|
draw_stack(deck->stock);
|
|
|
|
draw_stack(deck->waste_pile);
|
|
|
|
|
|
|
|
draw_stack(deck->foundation_0);
|
|
|
|
draw_stack(deck->foundation_1);
|
|
|
|
draw_stack(deck->foundation_2);
|
|
|
|
draw_stack(deck->foundation_3);
|
|
|
|
|
|
|
|
draw_stack(deck->maneuvre_0);
|
|
|
|
draw_stack(deck->maneuvre_1);
|
|
|
|
draw_stack(deck->maneuvre_2);
|
|
|
|
draw_stack(deck->maneuvre_3);
|
|
|
|
draw_stack(deck->maneuvre_4);
|
|
|
|
draw_stack(deck->maneuvre_5);
|
|
|
|
draw_stack(deck->maneuvre_6);
|
2010-04-03 19:34:45 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|