C-ifying project.
This commit is contained in:
64
src/card.c
Normal file
64
src/card.c
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "card.h"
|
||||
#include "common.h"
|
||||
|
||||
void allocate_card(struct card **card) {
|
||||
if (!(*card = malloc(sizeof(**card)))) {
|
||||
fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
allocate_frame(&((*card)->frame));
|
||||
}
|
||||
|
||||
void initialize_card(struct card *card) {
|
||||
initialize_frame(card->frame);
|
||||
card->value = NO_VALUE;
|
||||
card->suit = NO_SUIT;
|
||||
card->face = NO_FACE;
|
||||
}
|
||||
|
||||
struct card *duplicate_card(struct card *card) {
|
||||
struct card *new_card;
|
||||
|
||||
allocate_card(&new_card);
|
||||
set_card(new_card,
|
||||
card->value,
|
||||
card->suit,
|
||||
card->face,
|
||||
card->frame->begin_y,
|
||||
card->frame->begin_x);
|
||||
|
||||
return(new_card);
|
||||
}
|
||||
|
||||
void free_card(struct card *card) {
|
||||
if (card) {
|
||||
free_frame(card->frame);
|
||||
}
|
||||
free(card);
|
||||
}
|
||||
|
||||
void set_card(struct card *card,
|
||||
enum value value,
|
||||
enum suit suit,
|
||||
enum face face,
|
||||
int begin_y,
|
||||
int begin_x) {
|
||||
set_frame(card->frame, begin_y, begin_x);
|
||||
card->value = value;
|
||||
card->suit = suit;
|
||||
card->face = face;
|
||||
}
|
||||
|
||||
void expose_card(struct card *card) {
|
||||
card->face = EXPOSED;
|
||||
}
|
||||
|
||||
void cover_card(struct card *card) {
|
||||
card->face = COVERED;
|
||||
}
|
||||
52
src/card.h
Normal file
52
src/card.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef CARD_H
|
||||
#define CARD_H
|
||||
|
||||
#include "frame.h"
|
||||
|
||||
enum value {
|
||||
NO_VALUE = -1,
|
||||
TWO = 2,
|
||||
THREE = 3,
|
||||
FOUR = 4,
|
||||
FIVE = 5,
|
||||
SIX = 6,
|
||||
SEVEN = 7,
|
||||
EIGHT = 8,
|
||||
NINE = 9,
|
||||
TEN = 10,
|
||||
JACK = 11,
|
||||
QUEEN = 12,
|
||||
KING = 13,
|
||||
ACE = 14
|
||||
};
|
||||
|
||||
enum suit {
|
||||
NO_SUIT = -1,
|
||||
DIAMONDS = 0,
|
||||
SPADES = 1,
|
||||
HEARTS = 2,
|
||||
CLUBS = 3
|
||||
};
|
||||
|
||||
enum face {
|
||||
NO_FACE = -1,
|
||||
COVERED = 0,
|
||||
EXPOSED = 1
|
||||
};
|
||||
|
||||
struct card {
|
||||
struct frame *frame;
|
||||
enum value value;
|
||||
enum suit suit;
|
||||
enum face face;
|
||||
};
|
||||
|
||||
void allocate_card(struct card **);
|
||||
void initialize_card(struct card *);
|
||||
struct card *duplicate_card(struct card *);
|
||||
void free_card(struct card *);
|
||||
void set_card(struct card *, enum value, enum suit, enum face, int, int);
|
||||
void expose_card(struct card *);
|
||||
void cover_card(struct card *);
|
||||
|
||||
#endif
|
||||
16
src/common.c
Normal file
16
src/common.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
char *tty_solitaire_error_message(int errno, char *file, int line) {
|
||||
char *message = malloc(sizeof(ERROR_MESSAGE_BUFFER_SIZE));
|
||||
snprintf(message,
|
||||
ERROR_MESSAGE_BUFFER_SIZE,
|
||||
"%s: %s (%s:%d)\n",
|
||||
program_name,
|
||||
strerror(errno),
|
||||
file,
|
||||
line - 1);
|
||||
return(message);
|
||||
}
|
||||
8
src/common.h
Normal file
8
src/common.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
extern const char *program_name;
|
||||
#define ERROR_MESSAGE_BUFFER_SIZE 100
|
||||
char *tty_solitaire_error_message(int, char *, int);
|
||||
|
||||
#endif
|
||||
31
src/curses.c
Normal file
31
src/curses.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
#include <ncurses.h>
|
||||
#include <locale.h>
|
||||
#include "curses.h"
|
||||
|
||||
void initialize_curses() {
|
||||
setlocale(LC_ALL, "en_US.utf-8"); /* Support unicode characters. */
|
||||
initscr();
|
||||
raw(); /* Disable line buffers. */
|
||||
noecho();
|
||||
keypad(stdscr, TRUE); /* Enable arrow keys. */
|
||||
start_color(); /* I want colors. */
|
||||
curs_set(FALSE); /* Invisible cursor. */
|
||||
set_escdelay(0);
|
||||
assume_default_colors(COLOR_WHITE, COLOR_GREEN);
|
||||
|
||||
init_pair(1, COLOR_BLACK, COLOR_WHITE);
|
||||
init_pair(2, COLOR_RED, COLOR_WHITE);
|
||||
init_pair(3, COLOR_WHITE, COLOR_BLUE);
|
||||
init_pair(4, COLOR_WHITE, COLOR_GREEN);
|
||||
}
|
||||
|
||||
void end_curses() {
|
||||
endwin();
|
||||
puts("Game finished.");
|
||||
}
|
||||
|
||||
void clear_screen() {
|
||||
clear();
|
||||
refresh();
|
||||
}
|
||||
8
src/curses.h
Normal file
8
src/curses.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef TTY_SOLITAIRE_CURSES_H
|
||||
#define TTY_SOLITAIRE_CURSES_H
|
||||
|
||||
void initialize_curses();
|
||||
void end_curses();
|
||||
void clear_screen();
|
||||
|
||||
#endif
|
||||
100
src/cursor.c
Normal file
100
src/cursor.c
Normal file
@@ -0,0 +1,100 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ncurses.h>
|
||||
#include "display.h"
|
||||
#include "game.h"
|
||||
#include "cursor.h"
|
||||
#include "common.h"
|
||||
|
||||
void allocate_cursor(struct cursor **cursor) {
|
||||
if (!(*cursor = malloc(sizeof(**cursor)))) {
|
||||
fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
|
||||
exit(errno);
|
||||
} else {
|
||||
(*cursor)->window = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void initialize_cursor(struct cursor *cursor) {
|
||||
cursor->window = newwin(0, 0, cursor->y, cursor->x);
|
||||
cursor->x = CURSOR_BEGIN_X;
|
||||
cursor->y = CURSOR_BEGIN_Y;
|
||||
cursor->marked = false;
|
||||
}
|
||||
|
||||
void free_cursor(struct cursor *cursor) {
|
||||
if (cursor) {
|
||||
delwin(cursor->window);
|
||||
}
|
||||
free(cursor);
|
||||
}
|
||||
|
||||
void mark_cursor(struct cursor *cursor) {
|
||||
cursor->marked = true;
|
||||
}
|
||||
|
||||
void unmark_cursor(struct cursor *cursor) {
|
||||
cursor->marked = false;
|
||||
}
|
||||
|
||||
void move_cursor(struct cursor *cursor, enum movement movement) {
|
||||
switch (movement) {
|
||||
case LEFT:
|
||||
if (cursor->x > CURSOR_BEGIN_X) {
|
||||
erase_cursor(cursor);
|
||||
cursor->x = cursor->x - 8;
|
||||
if (cursor->y > CURSOR_BEGIN_Y) {
|
||||
move_cursor(cursor, UP);
|
||||
move_cursor(cursor, DOWN);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DOWN:
|
||||
if (cursor->y == CURSOR_BEGIN_Y) {
|
||||
erase_cursor(cursor);
|
||||
switch (cursor->x - 3) {
|
||||
case MANEUVRE_0_BEGIN_X:
|
||||
cursor->y = cursor->y + 7 + length(deck->maneuvre[0]);
|
||||
break;
|
||||
case MANEUVRE_1_BEGIN_X:
|
||||
cursor->y = cursor->y + 7 + length(deck->maneuvre[1]);
|
||||
break;
|
||||
case MANEUVRE_2_BEGIN_X:
|
||||
cursor->y = cursor->y + 7 + length(deck->maneuvre[2]);
|
||||
break;
|
||||
case MANEUVRE_3_BEGIN_X:
|
||||
cursor->y = cursor->y + 7 + length(deck->maneuvre[3]);
|
||||
break;
|
||||
case MANEUVRE_4_BEGIN_X:
|
||||
cursor->y = cursor->y + 7 + length(deck->maneuvre[4]);
|
||||
break;
|
||||
case MANEUVRE_5_BEGIN_X:
|
||||
cursor->y = cursor->y + 7 + length(deck->maneuvre[5]);
|
||||
break;
|
||||
case MANEUVRE_6_BEGIN_X:
|
||||
cursor->y = cursor->y + 7 + length(deck->maneuvre[6]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RIGHT:
|
||||
if (cursor->x < 49) {
|
||||
erase_cursor(cursor);
|
||||
cursor->x = cursor->x + 8;
|
||||
if (cursor->y > CURSOR_BEGIN_Y) {
|
||||
move_cursor(cursor, UP);
|
||||
move_cursor(cursor, DOWN);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UP:
|
||||
if (cursor->y > 1) {
|
||||
erase_cursor(cursor);
|
||||
cursor->y = CURSOR_BEGIN_Y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
45
src/cursor.h
Normal file
45
src/cursor.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef CURSOR_H
|
||||
#define CURSOR_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "deck.h"
|
||||
|
||||
#define CURSOR_BEGIN_X 4
|
||||
#define CURSOR_BEGIN_Y 7
|
||||
|
||||
#define CURSOR_INVALID_SPOT_X 20
|
||||
#define CURSOR_INVALID_SPOT_Y 7
|
||||
|
||||
#define CURSOR_STOCK_X 4
|
||||
#define CURSOR_WASTE_PILE_X 12
|
||||
#define CURSOR_FOUNDATION_0_X 28
|
||||
#define CURSOR_FOUNDATION_1_X 36
|
||||
#define CURSOR_FOUNDATION_2_X 44
|
||||
#define CURSOR_FOUNDATION_3_X 52
|
||||
#define CURSOR_MANEUVRE_0_X 4
|
||||
#define CURSOR_MANEUVRE_1_X 12
|
||||
#define CURSOR_MANEUVRE_2_X 20
|
||||
#define CURSOR_MANEUVRE_3_X 28
|
||||
#define CURSOR_MANEUVRE_4_X 36
|
||||
#define CURSOR_MANEUVRE_5_X 44
|
||||
#define CURSOR_MANEUVRE_6_X 52
|
||||
|
||||
struct cursor {
|
||||
WINDOW *window;
|
||||
int x;
|
||||
int y;
|
||||
bool marked;
|
||||
};
|
||||
|
||||
enum movement { LEFT, DOWN, UP, RIGHT };
|
||||
|
||||
extern struct deck *deck;
|
||||
|
||||
void allocate_cursor(struct cursor **);
|
||||
void initialize_cursor(struct cursor *);
|
||||
void free_cursor(struct cursor *);
|
||||
void mark_cursor(struct cursor *);
|
||||
void unmark_cursor(struct cursor *);
|
||||
void move_cursor(struct cursor *, enum movement);
|
||||
|
||||
#endif
|
||||
48
src/deck.c
Normal file
48
src/deck.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "deck.h"
|
||||
#include "common.h"
|
||||
|
||||
void allocate_deck(struct deck **deck) {
|
||||
if (!(*deck = malloc(sizeof(**deck)))) {
|
||||
fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
allocate_stack(&((*deck)->stock));
|
||||
allocate_stack(&((*deck)->waste_pile));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
allocate_stack(&((*deck)->foundation[i]));
|
||||
}
|
||||
for (int i = 0; i < 7; i++) {
|
||||
allocate_stack(&((*deck)->maneuvre[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void initialize_deck(struct deck *deck) {
|
||||
initialize_stack(deck->stock);
|
||||
initialize_stack(deck->waste_pile);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
initialize_stack(deck->foundation[i]);
|
||||
}
|
||||
for (int i = 0; i < 7; i++) {
|
||||
initialize_stack(deck->maneuvre[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void free_deck(struct deck *deck) {
|
||||
if (deck) {
|
||||
free_stack(deck->stock);
|
||||
free_stack(deck->waste_pile);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
free_stack(deck->foundation[i]);
|
||||
}
|
||||
for (int i = 0; i < 7; i++) {
|
||||
free_stack(deck->maneuvre[i]);
|
||||
}
|
||||
}
|
||||
free(deck);
|
||||
}
|
||||
17
src/deck.h
Normal file
17
src/deck.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef DECK_H
|
||||
#define DECK_H
|
||||
|
||||
#include "stack.h"
|
||||
|
||||
struct deck {
|
||||
struct stack *stock;
|
||||
struct stack *waste_pile;
|
||||
struct stack *foundation[4];
|
||||
struct stack *maneuvre[7];
|
||||
};
|
||||
|
||||
void allocate_deck(struct deck **);
|
||||
void initialize_deck(struct deck *);
|
||||
void free_deck(struct deck *);
|
||||
|
||||
#endif
|
||||
157
src/display.c
Normal file
157
src/display.c
Normal file
@@ -0,0 +1,157 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ncurses.h>
|
||||
#include "game.h"
|
||||
#include "display.h"
|
||||
#include "common.h"
|
||||
|
||||
static char *card_suit(enum suit suit) {
|
||||
char *card_suit;
|
||||
|
||||
if (!(card_suit = malloc(4 * sizeof(*card_suit)))) {
|
||||
fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
switch(suit) {
|
||||
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;
|
||||
default: strcpy(card_suit, "?");
|
||||
}
|
||||
|
||||
return(card_suit);
|
||||
}
|
||||
|
||||
static char *card_value(enum value value) {
|
||||
char *card_value;
|
||||
|
||||
if (!(card_value = malloc(2 * sizeof(*card_value)))) {
|
||||
fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void erase_card(struct card *card) {
|
||||
werase(card->frame->window);
|
||||
wbkgd(card->frame->window, WHITE_ON_GREEN);
|
||||
wrefresh(card->frame->window);
|
||||
}
|
||||
|
||||
void erase_stack(struct stack *stack) {
|
||||
if (maneuvre_stack(stack)) {
|
||||
for (; stack; stack = stack->next) {
|
||||
erase_card(stack->card);
|
||||
}
|
||||
} else {
|
||||
erase_card(stack->card);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_value(struct card *card) {
|
||||
mvwprintw(card->frame->window, 0, 0, card_value(card->value));
|
||||
mvwprintw(card->frame->window,
|
||||
4,
|
||||
6 - (strlen(card_value(card->value)) - 1),
|
||||
card_value(card->value));
|
||||
}
|
||||
|
||||
void draw_suit(struct card *card) {
|
||||
if (card->suit % 2 == 0) {
|
||||
wattron(card->frame->window, COLOR_PAIR(RED_ON_WHITE));
|
||||
} else {
|
||||
wattron(card->frame->window, COLOR_PAIR(BLACK_ON_WHITE));
|
||||
}
|
||||
mvwprintw(card->frame->window, 0, 1 + (strlen(card_value(card->value) + 1)),
|
||||
card_suit(card->suit));
|
||||
mvwprintw(card->frame->window, 4, 5 - (strlen(card_value(card->value) + 1)),
|
||||
card_suit(card->suit));
|
||||
if (card->suit % 2 == 0) {
|
||||
wattroff(card->frame->window, COLOR_PAIR(RED_ON_WHITE));
|
||||
} else {
|
||||
wattroff(card->frame->window, COLOR_PAIR(BLACK_ON_WHITE));
|
||||
}
|
||||
}
|
||||
|
||||
void draw_front(struct card *card) {
|
||||
wbkgd(card->frame->window, COLOR_PAIR(BLACK_ON_WHITE));
|
||||
draw_value(card);
|
||||
draw_suit(card);
|
||||
}
|
||||
|
||||
void draw_back(struct card *card) {
|
||||
wbkgd(card->frame->window, COLOR_PAIR(WHITE_ON_BLUE));
|
||||
}
|
||||
|
||||
void draw_card(struct card *card) {
|
||||
if (card->face == EXPOSED) {
|
||||
draw_front(card);
|
||||
} else {
|
||||
draw_back(card);
|
||||
}
|
||||
wrefresh(card->frame->window);
|
||||
}
|
||||
|
||||
void draw_stack(struct stack *stack) {
|
||||
erase_stack(stack);
|
||||
if (empty(stack)) {
|
||||
box(stack->card->frame->window, 0, 0);
|
||||
wrefresh(stack->card->frame->window);
|
||||
} else {
|
||||
if (maneuvre_stack(stack)) {
|
||||
struct stack *reversed_stack = reverse(stack);
|
||||
for (struct stack *i = reversed_stack; i; i = i->next) {
|
||||
draw_card(i->card);
|
||||
}
|
||||
} else {
|
||||
draw_card(stack->card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void draw_deck(struct deck *deck) {
|
||||
draw_stack(deck->stock);
|
||||
draw_stack(deck->waste_pile);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
draw_stack(deck->foundation[i]);
|
||||
}
|
||||
for (int i = 0; i < 7; i++) {
|
||||
draw_stack(deck->maneuvre[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_cursor(struct cursor *cursor) {
|
||||
if (cursor->marked) {
|
||||
mvwaddch(cursor->window, cursor->y, cursor->x, '@');
|
||||
} else {
|
||||
mvwaddch(cursor->window, cursor->y, cursor->x, '*');
|
||||
}
|
||||
wrefresh(cursor->window);
|
||||
}
|
||||
|
||||
void erase_cursor(struct cursor *cursor) {
|
||||
mvwdelch(cursor->window, cursor->y, cursor->x);
|
||||
}
|
||||
32
src/display.h
Normal file
32
src/display.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef DISPLAY_H
|
||||
#define DISPLAY_H
|
||||
|
||||
#include "card.h"
|
||||
#include "stack.h"
|
||||
#include "deck.h"
|
||||
#include "cursor.h"
|
||||
|
||||
#define EMPTY_STACKS_NUMBER 13
|
||||
|
||||
#define DIAMONDS_SYMBOL "\u2666"
|
||||
#define SPADES_SYMBOL "\u2660"
|
||||
#define HEARTS_SYMBOL "\u2665"
|
||||
#define CLUBS_SYMBOL "\u2663"
|
||||
|
||||
#define BLACK_ON_WHITE 1
|
||||
#define RED_ON_WHITE 2
|
||||
#define WHITE_ON_BLUE 3
|
||||
#define WHITE_ON_GREEN 4
|
||||
|
||||
void erase_stack(struct stack *);
|
||||
void draw_value(struct card *);
|
||||
void draw_suit(struct card *);
|
||||
void draw_front(struct card *);
|
||||
void draw_back(struct card *);
|
||||
void draw_card(struct card *);
|
||||
void draw_stack(struct stack *);
|
||||
void draw_deck(struct deck *);
|
||||
void draw_cursor(struct cursor *);
|
||||
void erase_cursor(struct cursor *);
|
||||
|
||||
#endif
|
||||
42
src/frame.c
Normal file
42
src/frame.c
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "frame.h"
|
||||
#include "common.h"
|
||||
|
||||
void allocate_frame(struct frame **frame) {
|
||||
if (!(*frame = malloc(sizeof(**frame)))) {
|
||||
fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
|
||||
exit(errno);
|
||||
}
|
||||
(*frame)->window = newwin(FRAME_HEIGHT, FRAME_WIDTH, 0, 0);
|
||||
}
|
||||
|
||||
void initialize_frame(struct frame *frame) {
|
||||
frame->begin_y = 0;
|
||||
frame->begin_x = 0;
|
||||
}
|
||||
|
||||
struct frame *duplicate_frame(struct frame *frame) {
|
||||
struct frame *new_frame;
|
||||
|
||||
allocate_frame(&new_frame);
|
||||
set_frame(new_frame, frame->begin_y, frame->begin_x);
|
||||
|
||||
return(new_frame);
|
||||
}
|
||||
|
||||
void free_frame(struct frame *frame) {
|
||||
if (frame) {
|
||||
delwin(frame->window);
|
||||
}
|
||||
free(frame);
|
||||
}
|
||||
|
||||
void set_frame(struct frame *frame, int begin_y, int begin_x) {
|
||||
frame->begin_y = begin_y;
|
||||
frame->begin_x = begin_x;
|
||||
mvwin(frame->window, begin_y, begin_x);
|
||||
}
|
||||
21
src/frame.h
Normal file
21
src/frame.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef FRAME_H
|
||||
#define FRAME_H
|
||||
|
||||
#include <ncurses.h>
|
||||
|
||||
#define FRAME_WIDTH 7
|
||||
#define FRAME_HEIGHT 5
|
||||
|
||||
struct frame {
|
||||
WINDOW *window;
|
||||
int begin_y;
|
||||
int begin_x;
|
||||
};
|
||||
|
||||
void allocate_frame(struct frame **);
|
||||
void initialize_frame(struct frame *);
|
||||
struct frame *duplicate_frame(struct frame *);
|
||||
void free_frame(struct frame *);
|
||||
void set_frame(struct frame *, int, int);
|
||||
|
||||
#endif
|
||||
205
src/game.c
Normal file
205
src/game.c
Normal file
@@ -0,0 +1,205 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "curses.h"
|
||||
#include "common.h"
|
||||
#include "game.h"
|
||||
|
||||
int foundation_begin_x(int x) {
|
||||
switch (x) {
|
||||
case 0: return(FOUNDATION_0_BEGIN_X); break;
|
||||
case 1: return(FOUNDATION_1_BEGIN_X); break;
|
||||
case 2: return(FOUNDATION_2_BEGIN_X); break;
|
||||
case 3: return(FOUNDATION_3_BEGIN_X); break;
|
||||
default:
|
||||
end_curses();
|
||||
end_game();
|
||||
assert(false && "invalid stack");
|
||||
}
|
||||
}
|
||||
|
||||
int maneuvre_begin_x(int x) {
|
||||
switch (x) {
|
||||
case 0: return(MANEUVRE_0_BEGIN_X); break;
|
||||
case 1: return(MANEUVRE_1_BEGIN_X); break;
|
||||
case 2: return(MANEUVRE_2_BEGIN_X); break;
|
||||
case 3: return(MANEUVRE_3_BEGIN_X); break;
|
||||
case 4: return(MANEUVRE_4_BEGIN_X); break;
|
||||
case 5: return(MANEUVRE_5_BEGIN_X); break;
|
||||
case 6: return(MANEUVRE_6_BEGIN_X); break;
|
||||
default:
|
||||
end_curses();
|
||||
end_game();
|
||||
assert(false && "maneuvre_begin_x called x < 0 || x > 6");
|
||||
}
|
||||
}
|
||||
|
||||
bool stock_stack(struct stack *stack) {
|
||||
return(stack && stack->card && stack->card->frame &&
|
||||
(stack->card->frame->begin_y == STOCK_BEGIN_Y) &&
|
||||
(stack->card->frame->begin_x == STOCK_BEGIN_X));
|
||||
}
|
||||
|
||||
bool waste_pile_stack(struct stack *stack) {
|
||||
return(stack && stack->card && stack->card->frame &&
|
||||
(stack->card->frame->begin_y == WASTE_PILE_BEGIN_Y) &&
|
||||
(stack->card->frame->begin_x == WASTE_PILE_BEGIN_X));
|
||||
}
|
||||
|
||||
bool foundation_stack(struct stack *stack) {
|
||||
return(stack && stack->card && stack->card->frame &&
|
||||
stack->card->frame->begin_y == FOUNDATION_BEGIN_Y &&
|
||||
(stack->card->frame->begin_x == FOUNDATION_0_BEGIN_X ||
|
||||
stack->card->frame->begin_x == FOUNDATION_1_BEGIN_X ||
|
||||
stack->card->frame->begin_x == FOUNDATION_2_BEGIN_X ||
|
||||
stack->card->frame->begin_x == FOUNDATION_3_BEGIN_X));
|
||||
}
|
||||
|
||||
bool maneuvre_stack(struct stack *stack) {
|
||||
return(stack && stack->card && stack->card->frame &&
|
||||
stack->card->frame->begin_y >= MANEUVRE_BEGIN_Y &&
|
||||
(stack->card->frame->begin_x == MANEUVRE_0_BEGIN_X ||
|
||||
stack->card->frame->begin_x == MANEUVRE_1_BEGIN_X ||
|
||||
stack->card->frame->begin_x == MANEUVRE_2_BEGIN_X ||
|
||||
stack->card->frame->begin_x == MANEUVRE_3_BEGIN_X ||
|
||||
stack->card->frame->begin_x == MANEUVRE_4_BEGIN_X ||
|
||||
stack->card->frame->begin_x == MANEUVRE_5_BEGIN_X ||
|
||||
stack->card->frame->begin_x == MANEUVRE_6_BEGIN_X));
|
||||
}
|
||||
|
||||
bool valid_move(struct stack *origin, struct stack *destination) {
|
||||
if (stock_stack(origin)) {
|
||||
if (waste_pile_stack(destination)) {
|
||||
return(true);
|
||||
} else {
|
||||
return(false);
|
||||
}
|
||||
} else if (waste_pile_stack(origin)) {
|
||||
if (foundation_stack(destination) || maneuvre_stack(destination)) {
|
||||
return(true);
|
||||
} else {
|
||||
return(false);
|
||||
}
|
||||
} else if (foundation_stack(origin)) {
|
||||
if ((foundation_stack(destination) && origin != destination) || maneuvre_stack(destination)) {
|
||||
return(true);
|
||||
} else {
|
||||
return(false);
|
||||
}
|
||||
} else if (maneuvre_stack(origin)) {
|
||||
if ((maneuvre_stack(destination) && origin != destination) || foundation_stack(destination)) {
|
||||
return(true);
|
||||
} else {
|
||||
return(false);
|
||||
}
|
||||
} else {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
void move_card(struct stack **origin, struct stack **destination) {
|
||||
struct card *tmp;
|
||||
if ((tmp = pop(origin))) {
|
||||
int destination_y = (*destination)->card->frame->begin_y;
|
||||
int destination_x = (*destination)->card->frame->begin_x;
|
||||
if (!empty(*destination) && maneuvre_stack(*destination)) {
|
||||
destination_y++;
|
||||
}
|
||||
push(destination, tmp);
|
||||
set_frame((*destination)->card->frame, destination_y, destination_x);
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_deck(struct deck *deck) {
|
||||
struct card *card[NUMBER_OF_CARDS];
|
||||
|
||||
for (int i = TWO; i <= ACE; i++) {
|
||||
for (int j = DIAMONDS; j <= CLUBS; j++) {
|
||||
int index = 4 * (i - TWO) + j;
|
||||
allocate_card(&(card[index]));
|
||||
set_card(card[index], i, j, COVERED, 1, 1);
|
||||
push(&(deck->stock), card[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void shuffle_deck(struct deck *deck) {
|
||||
struct card **card, tmp;
|
||||
int random;
|
||||
|
||||
if (!(card = malloc(NUMBER_OF_CARDS * sizeof(*card)))) {
|
||||
fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CARDS; i++) {
|
||||
card[i] = pop(&(deck->stock));
|
||||
}
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CARDS - 1; i++) {
|
||||
random = i + (rand() % (NUMBER_OF_CARDS) - i);
|
||||
tmp = *card[i];
|
||||
*card[i] = (*card[random]);
|
||||
*card[random] = tmp;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CARDS; i++) {
|
||||
push(&(deck->stock), card[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void deal_cards(struct deck *deck) {
|
||||
for (int i = 0; i < 7; i++) {
|
||||
move_card(&(deck->stock), &(deck->maneuvre[i]));
|
||||
expose_card(deck->maneuvre[i]->card);
|
||||
for (int j = i + 1; j < 7; j++) {
|
||||
move_card(&(deck->stock), &(deck->maneuvre[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void greet_player() {
|
||||
mvprintw(10, 27, "Welcome to tty-solitaire.");
|
||||
mvprintw(11, 8, "Move with \u2190\u2191\u2192\u2193 or hjkl. Use the space bar to mark and move cards.");
|
||||
mvprintw(12, 19, "Press the space bar to play or q to quit.");
|
||||
}
|
||||
|
||||
void initialize_game() {
|
||||
clear_screen();
|
||||
|
||||
allocate_cursor(&cursor);
|
||||
initialize_cursor(cursor);
|
||||
|
||||
allocate_deck(&deck);
|
||||
initialize_deck(deck);
|
||||
|
||||
/* Setting initial stacks' coordinates. */
|
||||
set_frame(deck->stock->card->frame, STOCK_BEGIN_Y, STOCK_BEGIN_X);
|
||||
set_frame(deck->waste_pile->card->frame, WASTE_PILE_BEGIN_Y, WASTE_PILE_BEGIN_X);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
set_frame(deck->foundation[i]->card->frame, FOUNDATION_BEGIN_Y, foundation_begin_x(i));
|
||||
}
|
||||
for (int i = 0; i < 7; i++) {
|
||||
set_frame(deck->maneuvre[i]->card->frame, MANEUVRE_BEGIN_Y, maneuvre_begin_x(i));
|
||||
}
|
||||
|
||||
fill_deck(deck);
|
||||
shuffle_deck(deck);
|
||||
deal_cards(deck);
|
||||
|
||||
draw_cursor(cursor);
|
||||
draw_deck(deck);
|
||||
}
|
||||
|
||||
void end_game() {
|
||||
free_deck(deck);
|
||||
free_cursor(cursor);
|
||||
}
|
||||
43
src/game.h
Normal file
43
src/game.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef GAME_H
|
||||
#define GAME_H
|
||||
|
||||
#include "stack.h"
|
||||
#include "deck.h"
|
||||
#include "cursor.h"
|
||||
|
||||
#define NUMBER_OF_CARDS 52
|
||||
|
||||
#define STOCK_BEGIN_X 1
|
||||
#define STOCK_BEGIN_Y 1
|
||||
|
||||
#define WASTE_PILE_BEGIN_X 9
|
||||
#define WASTE_PILE_BEGIN_Y 1
|
||||
|
||||
#define FOUNDATION_BEGIN_Y 1
|
||||
#define FOUNDATION_0_BEGIN_X 25
|
||||
#define FOUNDATION_1_BEGIN_X 33
|
||||
#define FOUNDATION_2_BEGIN_X 41
|
||||
#define FOUNDATION_3_BEGIN_X 49
|
||||
|
||||
#define MANEUVRE_BEGIN_Y 9
|
||||
#define MANEUVRE_0_BEGIN_X 1
|
||||
#define MANEUVRE_1_BEGIN_X 9
|
||||
#define MANEUVRE_2_BEGIN_X 17
|
||||
#define MANEUVRE_3_BEGIN_X 25
|
||||
#define MANEUVRE_4_BEGIN_X 33
|
||||
#define MANEUVRE_5_BEGIN_X 41
|
||||
#define MANEUVRE_6_BEGIN_X 49
|
||||
|
||||
struct deck *deck;
|
||||
struct cursor *cursor;
|
||||
|
||||
int foundation_begin_x(int);
|
||||
int maneuvre_begin_x(int);
|
||||
bool valid_move(struct stack *, struct stack *);
|
||||
bool maneuvre_stack(struct stack *);
|
||||
void move_card(struct stack **, struct stack **);
|
||||
void greet_player();
|
||||
void initialize_game();
|
||||
void end_game();
|
||||
|
||||
#endif
|
||||
143
src/keyboard.c
Normal file
143
src/keyboard.c
Normal file
@@ -0,0 +1,143 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "card.h"
|
||||
#include "game.h"
|
||||
#include "display.h"
|
||||
#include "curses.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
static bool cursor_on_stock(struct cursor *cursor) {
|
||||
return((cursor->x == CURSOR_BEGIN_X) && (cursor->y == CURSOR_BEGIN_Y));
|
||||
}
|
||||
|
||||
static struct stack **cursor_stack(struct cursor *cursor) {
|
||||
if (cursor->y == CURSOR_BEGIN_Y) {
|
||||
switch (cursor->x) {
|
||||
case CURSOR_STOCK_X: return(&(deck->stock));
|
||||
case CURSOR_WASTE_PILE_X: return(&(deck->waste_pile));
|
||||
case CURSOR_FOUNDATION_0_X: return(&(deck->foundation[0]));
|
||||
case CURSOR_FOUNDATION_1_X: return(&(deck->foundation[1]));
|
||||
case CURSOR_FOUNDATION_2_X: return(&(deck->foundation[2]));
|
||||
case CURSOR_FOUNDATION_3_X: return(&(deck->foundation[3]));
|
||||
default: assert(false && "invalid stack");
|
||||
}
|
||||
} else {
|
||||
switch (cursor->x) {
|
||||
case CURSOR_MANEUVRE_0_X: return(&(deck->maneuvre[0]));
|
||||
case CURSOR_MANEUVRE_1_X: return(&(deck->maneuvre[1]));
|
||||
case CURSOR_MANEUVRE_2_X: return(&(deck->maneuvre[2]));
|
||||
case CURSOR_MANEUVRE_3_X: return(&(deck->maneuvre[3]));
|
||||
case CURSOR_MANEUVRE_4_X: return(&(deck->maneuvre[4]));
|
||||
case CURSOR_MANEUVRE_5_X: return(&(deck->maneuvre[5]));
|
||||
case CURSOR_MANEUVRE_6_X: return(&(deck->maneuvre[6]));
|
||||
default: assert(false && "invalid stack");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool cursor_on_invalid_spot(struct cursor *cursor) {
|
||||
return(cursor->x == CURSOR_INVALID_SPOT_X &&
|
||||
cursor->y == CURSOR_INVALID_SPOT_Y);
|
||||
}
|
||||
|
||||
static void handle_stock_event() {
|
||||
if (!empty(deck->stock)) {
|
||||
move_card(&(deck->stock), &(deck->waste_pile));
|
||||
expose_card(deck->waste_pile->card);
|
||||
draw_stack(deck->stock);
|
||||
draw_stack(deck->waste_pile);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_card_movement(struct cursor *cursor) {
|
||||
struct stack **origin = cursor_stack(cursor);
|
||||
struct stack **destination;
|
||||
int option;
|
||||
|
||||
if (cursor_on_invalid_spot(cursor) || empty(*origin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mark_cursor(cursor);
|
||||
draw_cursor(cursor);
|
||||
|
||||
while (1) {
|
||||
switch (option = getch()) {
|
||||
case KEY_ESCAPE:
|
||||
if (cursor->marked) {
|
||||
unmark_cursor(cursor);
|
||||
draw_cursor(cursor);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
case KEY_LEFT:
|
||||
move_cursor(cursor, LEFT);
|
||||
draw_cursor(cursor);
|
||||
break;
|
||||
case 'j':
|
||||
case KEY_DOWN:
|
||||
move_cursor(cursor, DOWN);
|
||||
draw_cursor(cursor);
|
||||
break;
|
||||
case 'k':
|
||||
case KEY_UP:
|
||||
move_cursor(cursor, UP);
|
||||
draw_cursor(cursor);
|
||||
break;
|
||||
case 'l':
|
||||
case KEY_RIGHT:
|
||||
move_cursor(cursor, RIGHT);
|
||||
draw_cursor(cursor);
|
||||
break;
|
||||
case KEY_SPACEBAR:
|
||||
destination = cursor_stack(cursor);
|
||||
if (valid_move(*origin, *destination)) {
|
||||
erase_stack(*origin);
|
||||
move_card(origin, destination);
|
||||
draw_stack(*origin);
|
||||
draw_stack(*destination);
|
||||
}
|
||||
unmark_cursor(cursor);
|
||||
draw_cursor(cursor);
|
||||
return;
|
||||
case 'q':
|
||||
case 'Q':
|
||||
end_curses();
|
||||
end_game();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_keyboard_event(int key) {
|
||||
switch (key) {
|
||||
case 'h':
|
||||
case KEY_LEFT:
|
||||
move_cursor(cursor, LEFT);
|
||||
draw_cursor(cursor);
|
||||
break;
|
||||
case 'j':
|
||||
case KEY_DOWN:
|
||||
move_cursor(cursor, DOWN);
|
||||
draw_cursor(cursor);
|
||||
break;
|
||||
case 'k':
|
||||
case KEY_UP:
|
||||
move_cursor(cursor, UP);
|
||||
draw_cursor(cursor);
|
||||
break;
|
||||
case 'l':
|
||||
case KEY_RIGHT:
|
||||
move_cursor(cursor, RIGHT);
|
||||
draw_cursor(cursor);
|
||||
break;
|
||||
case KEY_SPACEBAR:
|
||||
if (cursor_on_stock(cursor)) {
|
||||
handle_stock_event();
|
||||
} else {
|
||||
handle_card_movement(cursor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
15
src/keyboard.h
Normal file
15
src/keyboard.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef KEYBOARD_H
|
||||
#define KEYBOARD_H
|
||||
|
||||
#include "deck.h"
|
||||
#include "cursor.h"
|
||||
|
||||
#define KEY_SPACEBAR 32
|
||||
#define KEY_ESCAPE 27
|
||||
|
||||
extern struct deck *deck;
|
||||
extern struct cursor *cursor;
|
||||
|
||||
void handle_keyboard_event();
|
||||
|
||||
#endif
|
||||
122
src/stack.c
Normal file
122
src/stack.c
Normal file
@@ -0,0 +1,122 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "stack.h"
|
||||
#include "common.h"
|
||||
|
||||
void allocate_stack(struct stack **stack) {
|
||||
if (!(*stack = malloc(sizeof(**stack)))) {
|
||||
fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
allocate_card(&((*stack)->card));
|
||||
}
|
||||
|
||||
void initialize_stack(struct stack *stack) {
|
||||
initialize_card(stack->card);
|
||||
stack->next = NULL;
|
||||
}
|
||||
|
||||
struct stack *duplicate_stack(struct stack *stack) {
|
||||
struct stack *iterator = stack;
|
||||
struct stack *tmp_stack, *new_stack;
|
||||
|
||||
allocate_stack(&new_stack);
|
||||
allocate_stack(&tmp_stack);
|
||||
initialize_stack(new_stack);
|
||||
initialize_stack(tmp_stack);
|
||||
for (iterator = stack; iterator; iterator = iterator->next) {
|
||||
push(&tmp_stack, duplicate_card(iterator->card));
|
||||
}
|
||||
while (!empty(tmp_stack)) {
|
||||
push(&new_stack, (pop(&tmp_stack)));
|
||||
}
|
||||
free_stack(tmp_stack);
|
||||
|
||||
return(new_stack);
|
||||
}
|
||||
|
||||
void free_stack(struct stack *stack) {
|
||||
struct stack *tmp;
|
||||
|
||||
for (; stack; stack = tmp) {
|
||||
tmp = stack->next;
|
||||
free_card(stack->card);
|
||||
free(stack);
|
||||
}
|
||||
}
|
||||
|
||||
bool empty(struct stack *stack) {
|
||||
return(stack->card->value == NO_VALUE &&
|
||||
stack->card->suit == NO_SUIT &&
|
||||
stack->card->face == NO_FACE &&
|
||||
!stack->next);
|
||||
}
|
||||
|
||||
int length(struct stack *stack) {
|
||||
int length = 0;
|
||||
|
||||
if (!empty(stack)) {
|
||||
for (length = 1; stack->next; stack = stack->next, length++)
|
||||
;
|
||||
}
|
||||
|
||||
return(length);
|
||||
}
|
||||
|
||||
void push(struct stack **stack, struct card *card) {
|
||||
if (card) {
|
||||
if (empty(*stack)) {
|
||||
(*stack)->card = card;
|
||||
} else {
|
||||
/* Allocating by hand because stack#allocate_stack would
|
||||
* have allocated an unwanted card object. */
|
||||
struct stack *new_stack = malloc(sizeof(*new_stack));
|
||||
new_stack->card = card;
|
||||
new_stack->next = (*stack);
|
||||
*stack = new_stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct card *pop(struct stack **stack) {
|
||||
if(empty(*stack)) {
|
||||
return(NULL);
|
||||
} else {
|
||||
struct card *popped_card = (*stack)->card;
|
||||
if (length(*stack) == 1) {
|
||||
/* Remembering the stack position before clearing it. */
|
||||
int begin_y = (*stack)->card->frame->begin_y;
|
||||
int begin_x = (*stack)->card->frame->begin_x;
|
||||
allocate_card(&((*stack)->card));
|
||||
/* An empty stack is a stack with a blank top card
|
||||
* and with stack->next == NULL. */
|
||||
set_card((*stack)->card, NO_VALUE, NO_SUIT, NO_FACE, begin_y, begin_x);
|
||||
(*stack)->next = NULL;
|
||||
} else {
|
||||
struct stack *tmp = *stack;
|
||||
*stack = (*stack)->next;
|
||||
free(tmp);
|
||||
}
|
||||
return(popped_card);
|
||||
}
|
||||
}
|
||||
|
||||
struct stack *reverse(struct stack *stack) {
|
||||
if (length(stack) > 1) {
|
||||
struct stack *tmp_stack, *iterator;
|
||||
|
||||
allocate_stack(&tmp_stack);
|
||||
initialize_stack(tmp_stack);
|
||||
for (iterator = stack; iterator; iterator = iterator->next) {
|
||||
push(&tmp_stack, iterator->card);
|
||||
}
|
||||
return(tmp_stack);
|
||||
} else {
|
||||
return(stack);
|
||||
}
|
||||
}
|
||||
21
src/stack.h
Normal file
21
src/stack.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef STACK_H
|
||||
#define STACK_H
|
||||
|
||||
#include "card.h"
|
||||
|
||||
struct stack {
|
||||
struct card *card;
|
||||
struct stack *next;
|
||||
};
|
||||
|
||||
void allocate_stack(struct stack **);
|
||||
void initialize_stack(struct stack *);
|
||||
struct stack *duplicate_stack(struct stack *);
|
||||
void free_stack(struct stack *);
|
||||
bool empty(struct stack *);
|
||||
int length(struct stack *);
|
||||
void push(struct stack **, struct card *);
|
||||
struct card *pop(struct stack **);
|
||||
struct stack *reverse(struct stack *);
|
||||
|
||||
#endif
|
||||
39
src/ttysolitaire.c
Normal file
39
src/ttysolitaire.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <stdlib.h>
|
||||
#include <ncurses.h>
|
||||
#include "curses.h"
|
||||
#include "game.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
const char *program_name;
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
program_name = *argv;
|
||||
int key;
|
||||
|
||||
initialize_curses();
|
||||
greet_player();
|
||||
|
||||
while (key != KEY_SPACEBAR) {
|
||||
switch (key = getch()) {
|
||||
case KEY_SPACEBAR:
|
||||
initialize_game();
|
||||
break;
|
||||
case 'q':
|
||||
case 'Q':
|
||||
end_curses();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if ((key = getch()) == 'q' || key == 'Q') {
|
||||
end_curses();
|
||||
end_game();
|
||||
exit(0);
|
||||
} else {
|
||||
handle_keyboard_event(key);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
Reference in New Issue
Block a user