Resizing works.
This commit is contained in:
		
							parent
							
								
									561b4ba599
								
							
						
					
					
						commit
						893f18a7e0
					
				@ -8,8 +8,7 @@
 | 
			
		||||
 | 
			
		||||
void card_malloc(struct card **card) {
 | 
			
		||||
  if (!(*card = malloc(sizeof(**card)))) {
 | 
			
		||||
    fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
 | 
			
		||||
    exit(errno);
 | 
			
		||||
    tty_solitaire_generic_error(errno, __FILE__, __LINE__);
 | 
			
		||||
  }
 | 
			
		||||
  frame_malloc(&((*card)->frame));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								src/common.c
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/common.c
									
									
									
									
									
								
							@ -1,16 +1,25 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <malloc.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ncurses.h>
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
char *tty_solitaire_error_message(int errno, char *file, int line) {
 | 
			
		||||
  char *message = malloc(sizeof(ERROR_MESSAGE_BUFFER_SIZE));
 | 
			
		||||
bool term_size_ok() {
 | 
			
		||||
  int lines, columns;
 | 
			
		||||
  getmaxyx(stdscr, lines, columns);
 | 
			
		||||
  return(lines >= MIN_TERM_LINES && columns >= MIN_TERM_COLS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tty_solitaire_generic_error(int errno, char *file, int line) {
 | 
			
		||||
  char message[TTY_SOLITAIRE_BUFSIZ];
 | 
			
		||||
  snprintf(message,
 | 
			
		||||
           ERROR_MESSAGE_BUFFER_SIZE,
 | 
			
		||||
           "%s: %s (%s:%d)\n",
 | 
			
		||||
           TTY_SOLITAIRE_BUFSIZ,
 | 
			
		||||
           "%s: %s (%s:%d)",
 | 
			
		||||
           program_name,
 | 
			
		||||
           strerror(errno),
 | 
			
		||||
           file,
 | 
			
		||||
           line - 1);
 | 
			
		||||
  return(message);
 | 
			
		||||
  fprintf(stderr, "%s\n", message);
 | 
			
		||||
  exit(errno);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								src/common.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/common.h
									
									
									
									
									
								
							@ -1,8 +1,17 @@
 | 
			
		||||
#ifndef TTY_SOLITAIRE_COMMON_H
 | 
			
		||||
#define TTY_SOLITAIRE_COMMON_H
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#define MIN_TERM_LINES 28
 | 
			
		||||
#define MIN_TERM_COLS 57
 | 
			
		||||
#define TTY_SOLITAIRE_BUFSIZ 100
 | 
			
		||||
 | 
			
		||||
#define SMALL_TERM_MSG "Please increase your terminal size to at least 57x28 or press q to quit."
 | 
			
		||||
 | 
			
		||||
extern const char *program_name;
 | 
			
		||||
#define ERROR_MESSAGE_BUFFER_SIZE 100
 | 
			
		||||
char *tty_solitaire_error_message(int, char *, int);
 | 
			
		||||
 | 
			
		||||
void tty_solitaire_generic_error(int, char *, int);
 | 
			
		||||
bool term_size_ok();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -11,8 +11,7 @@
 | 
			
		||||
 | 
			
		||||
void cursor_malloc(struct cursor **cursor) {
 | 
			
		||||
  if (!(*cursor = malloc(sizeof(**cursor)))) {
 | 
			
		||||
    fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
 | 
			
		||||
    exit(errno);
 | 
			
		||||
    tty_solitaire_generic_error(errno, __FILE__, __LINE__);
 | 
			
		||||
  }
 | 
			
		||||
  (*cursor)->window = newwin(1, 1, CURSOR_BEGIN_Y, CURSOR_BEGIN_X);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,7 @@
 | 
			
		||||
 | 
			
		||||
void deck_malloc(struct deck **deck) {
 | 
			
		||||
  if (!(*deck = malloc(sizeof(**deck)))) {
 | 
			
		||||
    fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
 | 
			
		||||
    exit(errno);
 | 
			
		||||
    tty_solitaire_generic_error(errno, __FILE__, __LINE__);
 | 
			
		||||
  }
 | 
			
		||||
  stack_malloc(&((*deck)->stock));
 | 
			
		||||
  stack_malloc(&((*deck)->waste_pile));
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,7 @@
 | 
			
		||||
 | 
			
		||||
void frame_malloc(struct frame **frame) {
 | 
			
		||||
  if (!(*frame = malloc(sizeof(**frame)))) {
 | 
			
		||||
    fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
 | 
			
		||||
    exit(errno);
 | 
			
		||||
    tty_solitaire_generic_error(errno, __FILE__, __LINE__);
 | 
			
		||||
  }
 | 
			
		||||
  (*frame)->window = newwin(FRAME_HEIGHT, FRAME_WIDTH, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -149,8 +149,7 @@ static void shuffle_deck(struct deck *deck) {
 | 
			
		||||
  int random;
 | 
			
		||||
 | 
			
		||||
  if (!(card = malloc(NUMBER_OF_CARDS * sizeof(*card)))) {
 | 
			
		||||
    fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
 | 
			
		||||
    exit(errno);
 | 
			
		||||
    tty_solitaire_generic_error(errno, __FILE__, __LINE__);
 | 
			
		||||
  }
 | 
			
		||||
  for (int i = 0; i < NUMBER_OF_CARDS; i++) {
 | 
			
		||||
    card[i] = stack_pop(&(deck->stock));
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										309
									
								
								src/keyboard.c
									
									
									
									
									
								
							
							
						
						
									
										309
									
								
								src/keyboard.c
									
									
									
									
									
								
							@ -1,4 +1,5 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <ncurses.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
@ -7,6 +8,18 @@
 | 
			
		||||
#include "game.h"
 | 
			
		||||
#include "cursor.h"
 | 
			
		||||
#include "gui.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
static void handle_term_resize() {
 | 
			
		||||
  clear();
 | 
			
		||||
  refresh();
 | 
			
		||||
  if (term_size_ok()) {
 | 
			
		||||
    draw_deck(deck);
 | 
			
		||||
    draw_cursor(cursor);
 | 
			
		||||
  } else {
 | 
			
		||||
    mvprintw(1, 1, SMALL_TERM_MSG);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME: this function does not work on stacks with no marked cards.
 | 
			
		||||
 * In that case it returns the stack's length. */
 | 
			
		||||
@ -35,12 +48,11 @@ static void unmark_cards(struct stack *stack) {
 | 
			
		||||
 | 
			
		||||
static void handle_card_movement(struct cursor *cursor) {
 | 
			
		||||
  struct stack **origin = cursor_stack(cursor);
 | 
			
		||||
  int option;
 | 
			
		||||
  int key;
 | 
			
		||||
 | 
			
		||||
  if (cursor_on_invalid_spot(cursor) || stack_empty(*origin)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (maneuvre_stack(*origin)) {
 | 
			
		||||
    erase_stack(*origin);
 | 
			
		||||
    card_mark((*origin)->card);
 | 
			
		||||
@ -51,8 +63,136 @@ static void handle_card_movement(struct cursor *cursor) {
 | 
			
		||||
  cursor_mark(cursor);
 | 
			
		||||
  draw_cursor(cursor);
 | 
			
		||||
 | 
			
		||||
  while (1) {
 | 
			
		||||
    switch (option = getch()) {
 | 
			
		||||
  for (;;) {
 | 
			
		||||
    if ((key = getch()) == 'q' || key == 'Q') {
 | 
			
		||||
      endwin();
 | 
			
		||||
      exit(0);
 | 
			
		||||
    }
 | 
			
		||||
    if (term_size_ok()) {
 | 
			
		||||
      switch (key) {
 | 
			
		||||
      case 'h':
 | 
			
		||||
      case 'j':
 | 
			
		||||
      case 'k':
 | 
			
		||||
      case 'l':
 | 
			
		||||
      case KEY_LEFT:
 | 
			
		||||
      case KEY_DOWN:
 | 
			
		||||
      case KEY_UP:
 | 
			
		||||
      case KEY_RIGHT:
 | 
			
		||||
        erase_cursor(cursor);
 | 
			
		||||
        cursor_move(cursor, cursor_direction(key));
 | 
			
		||||
        draw_cursor(cursor);
 | 
			
		||||
        break;
 | 
			
		||||
      case 'm':
 | 
			
		||||
        if (origin == cursor_stack(cursor) && maneuvre_stack(*origin)) {
 | 
			
		||||
          for (struct stack *i = *origin; i && i->next; i = i->next) {
 | 
			
		||||
            if (i->next->card->face == EXPOSED &&
 | 
			
		||||
                  (i->card->frame->begin_y - i->next->card->frame->begin_y) > 1) {
 | 
			
		||||
              erase_stack(*origin);
 | 
			
		||||
              card_mark(i->next->card);
 | 
			
		||||
              draw_stack(*origin);
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case 'n':
 | 
			
		||||
        if (origin == cursor_stack(cursor) && maneuvre_stack(*origin)) {
 | 
			
		||||
          for (struct stack *i = (*origin)->next; i; i = i->next) {
 | 
			
		||||
            if (i->next) {
 | 
			
		||||
              if ((i->card->frame->begin_y - i->next->card->frame->begin_y) > 1) {
 | 
			
		||||
                erase_stack(*origin);
 | 
			
		||||
                card_unmark(i->card);
 | 
			
		||||
                draw_stack(*origin);
 | 
			
		||||
                break;
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              if (i->card->frame->begin_y == (MANEUVRE_BEGIN_Y + 1)) {
 | 
			
		||||
                erase_stack(*origin);
 | 
			
		||||
                card_unmark(i->card);
 | 
			
		||||
                draw_stack(*origin);
 | 
			
		||||
                break;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case KEY_SPACEBAR:;
 | 
			
		||||
        /* http://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg259382.html */
 | 
			
		||||
        struct stack **destination = cursor_stack(cursor);
 | 
			
		||||
        int _marked_cards_count = marked_cards_count(*origin);
 | 
			
		||||
        if (maneuvre_stack(*origin) && _marked_cards_count > 0) {
 | 
			
		||||
          erase_stack(*origin);
 | 
			
		||||
          unmark_cards(*origin);
 | 
			
		||||
          draw_stack(*origin);
 | 
			
		||||
        }
 | 
			
		||||
        if (destination) {
 | 
			
		||||
          erase_stack(*origin);
 | 
			
		||||
          erase_cursor(cursor);
 | 
			
		||||
          if (_marked_cards_count > 1 &&
 | 
			
		||||
                maneuvre_stack(*origin) &&
 | 
			
		||||
                maneuvre_stack(*destination)) {
 | 
			
		||||
            struct stack *block = *origin;
 | 
			
		||||
            for (int i = 1; i < _marked_cards_count; block = block->next, i++)
 | 
			
		||||
              ;
 | 
			
		||||
            if (valid_move(block, *destination)) {
 | 
			
		||||
              move_block(origin, destination, _marked_cards_count);
 | 
			
		||||
            }
 | 
			
		||||
          } else {
 | 
			
		||||
            if (valid_move(*origin, *destination)) {
 | 
			
		||||
              if (maneuvre_stack(*destination)) {
 | 
			
		||||
                cursor->y++;
 | 
			
		||||
              }
 | 
			
		||||
              move_card(origin, destination);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          draw_stack(*origin);
 | 
			
		||||
          draw_stack(*destination);
 | 
			
		||||
          if (maneuvre_stack(*origin) && *origin == *destination) {
 | 
			
		||||
            erase_cursor(cursor);
 | 
			
		||||
            cursor->y--;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        cursor_unmark(cursor);
 | 
			
		||||
        draw_cursor(cursor);
 | 
			
		||||
        return;
 | 
			
		||||
      case KEY_ESCAPE:
 | 
			
		||||
        if (cursor_stack(cursor) == origin && maneuvre_stack(*origin)) {
 | 
			
		||||
          erase_cursor(cursor);
 | 
			
		||||
          cursor->y--;
 | 
			
		||||
        }
 | 
			
		||||
        if (marked_cards_count(*origin) > 0) {
 | 
			
		||||
          erase_stack(*origin);
 | 
			
		||||
          unmark_cards(*origin);
 | 
			
		||||
          draw_stack(*origin);
 | 
			
		||||
        }
 | 
			
		||||
        if (cursor->marked) {
 | 
			
		||||
          cursor_unmark(cursor);
 | 
			
		||||
          draw_cursor(cursor);
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
      case KEY_RESIZE:
 | 
			
		||||
        handle_term_resize();
 | 
			
		||||
        break;
 | 
			
		||||
      case 'q':
 | 
			
		||||
      case 'Q':
 | 
			
		||||
        endwin();
 | 
			
		||||
        game_end();
 | 
			
		||||
        exit(0);
 | 
			
		||||
      }
 | 
			
		||||
    } else if (key == KEY_RESIZE) {
 | 
			
		||||
      handle_term_resize();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void keyboard_event(int key) {
 | 
			
		||||
  if (key == 'q' || key == 'Q') {
 | 
			
		||||
    endwin();
 | 
			
		||||
    game_end();
 | 
			
		||||
    exit(0);
 | 
			
		||||
  }
 | 
			
		||||
  if (term_size_ok()) {
 | 
			
		||||
    switch (key) {
 | 
			
		||||
    case 'h':
 | 
			
		||||
    case 'j':
 | 
			
		||||
    case 'k':
 | 
			
		||||
@ -62,151 +202,46 @@ static void handle_card_movement(struct cursor *cursor) {
 | 
			
		||||
    case KEY_UP:
 | 
			
		||||
    case KEY_RIGHT:
 | 
			
		||||
      erase_cursor(cursor);
 | 
			
		||||
      cursor_move(cursor, cursor_direction(option));
 | 
			
		||||
      cursor_move(cursor, cursor_direction(key));
 | 
			
		||||
      draw_cursor(cursor);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'm':
 | 
			
		||||
      if (origin == cursor_stack(cursor) && maneuvre_stack(*origin)) {
 | 
			
		||||
        for (struct stack *i = *origin; i && i->next; i = i->next) {
 | 
			
		||||
          if (i->next->card->face == EXPOSED &&
 | 
			
		||||
                (i->card->frame->begin_y - i->next->card->frame->begin_y) > 1) {
 | 
			
		||||
            erase_stack(*origin);
 | 
			
		||||
            card_mark(i->next->card);
 | 
			
		||||
            draw_stack(*origin);
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case 'n':
 | 
			
		||||
      if (origin == cursor_stack(cursor) && maneuvre_stack(*origin)) {
 | 
			
		||||
        for (struct stack *i = (*origin)->next; i; i = i->next) {
 | 
			
		||||
          if (i->next) {
 | 
			
		||||
            if ((i->card->frame->begin_y - i->next->card->frame->begin_y) > 1) {
 | 
			
		||||
              erase_stack(*origin);
 | 
			
		||||
              card_unmark(i->card);
 | 
			
		||||
              draw_stack(*origin);
 | 
			
		||||
              break;
 | 
			
		||||
    case KEY_SPACEBAR:
 | 
			
		||||
      if (cursor_on_stock(cursor)) {
 | 
			
		||||
        if (stack_empty(deck->stock)) {
 | 
			
		||||
          if (game.passes_through_deck_left >= 1) {
 | 
			
		||||
            while (!stack_empty(deck->waste_pile)) {
 | 
			
		||||
              move_card(&(deck->waste_pile), &(deck->stock));
 | 
			
		||||
              card_cover(deck->stock->card);
 | 
			
		||||
            }
 | 
			
		||||
          } else {
 | 
			
		||||
            if (i->card->frame->begin_y == (MANEUVRE_BEGIN_Y + 1)) {
 | 
			
		||||
              erase_stack(*origin);
 | 
			
		||||
              card_unmark(i->card);
 | 
			
		||||
              draw_stack(*origin);
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case KEY_SPACEBAR:;
 | 
			
		||||
      /* http://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg259382.html */
 | 
			
		||||
      struct stack **destination = cursor_stack(cursor);
 | 
			
		||||
      int _marked_cards_count = marked_cards_count(*origin);
 | 
			
		||||
      if (maneuvre_stack(*origin) && _marked_cards_count > 0) {
 | 
			
		||||
        erase_stack(*origin);
 | 
			
		||||
        unmark_cards(*origin);
 | 
			
		||||
        draw_stack(*origin);
 | 
			
		||||
      }
 | 
			
		||||
      if (destination) {
 | 
			
		||||
        erase_stack(*origin);
 | 
			
		||||
        erase_cursor(cursor);
 | 
			
		||||
        if (_marked_cards_count > 1 &&
 | 
			
		||||
              maneuvre_stack(*origin) &&
 | 
			
		||||
              maneuvre_stack(*destination)) {
 | 
			
		||||
          struct stack *block = *origin;
 | 
			
		||||
          for (int i = 1; i < _marked_cards_count; block = block->next, i++)
 | 
			
		||||
            ;
 | 
			
		||||
          if (valid_move(block, *destination)) {
 | 
			
		||||
            move_block(origin, destination, _marked_cards_count);
 | 
			
		||||
            draw_stack(deck->stock);
 | 
			
		||||
            draw_stack(deck->waste_pile);
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          if (valid_move(*origin, *destination)) {
 | 
			
		||||
            if (maneuvre_stack(*destination)) {
 | 
			
		||||
              cursor->y++;
 | 
			
		||||
            }
 | 
			
		||||
            move_card(origin, destination);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        draw_stack(*origin);
 | 
			
		||||
        draw_stack(*destination);
 | 
			
		||||
        if (maneuvre_stack(*origin) && *origin == *destination) {
 | 
			
		||||
          erase_cursor(cursor);
 | 
			
		||||
          cursor->y--;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      cursor_unmark(cursor);
 | 
			
		||||
      draw_cursor(cursor);
 | 
			
		||||
      return;
 | 
			
		||||
    case KEY_ESCAPE:
 | 
			
		||||
      if (cursor_stack(cursor) == origin && maneuvre_stack(*origin)) {
 | 
			
		||||
        erase_cursor(cursor);
 | 
			
		||||
        cursor->y--;
 | 
			
		||||
      }
 | 
			
		||||
      if (marked_cards_count(*origin) > 0) {
 | 
			
		||||
        erase_stack(*origin);
 | 
			
		||||
        unmark_cards(*origin);
 | 
			
		||||
        draw_stack(*origin);
 | 
			
		||||
      }
 | 
			
		||||
      if (cursor->marked) {
 | 
			
		||||
        cursor_unmark(cursor);
 | 
			
		||||
        draw_cursor(cursor);
 | 
			
		||||
      }
 | 
			
		||||
      return;
 | 
			
		||||
    case 'q':
 | 
			
		||||
    case 'Q':
 | 
			
		||||
      endwin();
 | 
			
		||||
      game_end();
 | 
			
		||||
      exit(0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void keyboard_event(int key) {
 | 
			
		||||
  switch (key) {
 | 
			
		||||
  case 'h':
 | 
			
		||||
  case 'j':
 | 
			
		||||
  case 'k':
 | 
			
		||||
  case 'l':
 | 
			
		||||
  case KEY_LEFT:
 | 
			
		||||
  case KEY_DOWN:
 | 
			
		||||
  case KEY_UP:
 | 
			
		||||
  case KEY_RIGHT:
 | 
			
		||||
    erase_cursor(cursor);
 | 
			
		||||
    cursor_move(cursor, cursor_direction(key));
 | 
			
		||||
    draw_cursor(cursor);
 | 
			
		||||
    break;
 | 
			
		||||
  case KEY_SPACEBAR:
 | 
			
		||||
    if (cursor_on_stock(cursor)) {
 | 
			
		||||
      if (stack_empty(deck->stock)) {
 | 
			
		||||
        if (game.passes_through_deck_left >= 1) {
 | 
			
		||||
          while (!stack_empty(deck->waste_pile)) {
 | 
			
		||||
            move_card(&(deck->waste_pile), &(deck->stock));
 | 
			
		||||
            card_cover(deck->stock->card);
 | 
			
		||||
          move_card(&(deck->stock), &(deck->waste_pile));
 | 
			
		||||
          if (stack_empty(deck->stock)) {
 | 
			
		||||
            game.passes_through_deck_left--;
 | 
			
		||||
          }
 | 
			
		||||
          card_expose(deck->waste_pile->card);
 | 
			
		||||
          erase_stack(deck->waste_pile);
 | 
			
		||||
          draw_stack(deck->stock);
 | 
			
		||||
          draw_stack(deck->waste_pile);
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        move_card(&(deck->stock), &(deck->waste_pile));
 | 
			
		||||
        if (stack_empty(deck->stock)) {
 | 
			
		||||
          game.passes_through_deck_left--;
 | 
			
		||||
        struct card *card;
 | 
			
		||||
        if (cursor_stack(cursor) &&
 | 
			
		||||
              (card = (*cursor_stack(cursor))->card)->face == COVERED) {
 | 
			
		||||
          card_expose(card);
 | 
			
		||||
          draw_card(card);
 | 
			
		||||
        } else {
 | 
			
		||||
          handle_card_movement(cursor);
 | 
			
		||||
        }
 | 
			
		||||
        card_expose(deck->waste_pile->card);
 | 
			
		||||
        erase_stack(deck->waste_pile);
 | 
			
		||||
        draw_stack(deck->stock);
 | 
			
		||||
        draw_stack(deck->waste_pile);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      struct card *card;
 | 
			
		||||
      if (cursor_stack(cursor) &&
 | 
			
		||||
            (card = (*cursor_stack(cursor))->card)->face == COVERED) {
 | 
			
		||||
        card_expose(card);
 | 
			
		||||
        draw_card(card);
 | 
			
		||||
      } else {
 | 
			
		||||
        handle_card_movement(cursor);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case KEY_RESIZE:
 | 
			
		||||
      handle_term_resize();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
  } else if (key == KEY_RESIZE) {
 | 
			
		||||
    handle_term_resize();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -10,8 +10,7 @@
 | 
			
		||||
 | 
			
		||||
void stack_malloc(struct stack **stack) {
 | 
			
		||||
  if (!(*stack = malloc(sizeof(**stack)))) {
 | 
			
		||||
    fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
 | 
			
		||||
    exit(errno);
 | 
			
		||||
    tty_solitaire_generic_error(errno, __FILE__, __LINE__);
 | 
			
		||||
  }
 | 
			
		||||
  card_malloc(&((*stack)->card));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,6 @@
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include "gui.h"
 | 
			
		||||
#include "game.h"
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
@ -12,35 +11,9 @@
 | 
			
		||||
const char *program_name;
 | 
			
		||||
struct game game;
 | 
			
		||||
 | 
			
		||||
void draw_greeting() {
 | 
			
		||||
  mvprintw(8, 26, "Welcome to tty-solitaire.");
 | 
			
		||||
  mvprintw(10, 23, "Move with the arrow keys or hjkl.");
 | 
			
		||||
  mvprintw(11, 19, "Use the space bar to mark and move cards.");
 | 
			
		||||
  mvprintw(12, 16, "After marking a card you can use m to increase ");
 | 
			
		||||
  mvprintw(13, 17, "and n to decrease the number of marked cards.");
 | 
			
		||||
  mvprintw(15, 19, "Press the space bar to play or q to quit.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usage(const char *program_name) {
 | 
			
		||||
  printf("usage: %s [-v|--version] [-h|--help] [-p|--passes=NUMBER]\n", program_name);
 | 
			
		||||
  printf("  -v, --version  Show version\n");
 | 
			
		||||
  printf("  -h, --help     Show this message\n");
 | 
			
		||||
  printf("  -p, --passes   Number of passes through the deck\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void version() {
 | 
			
		||||
  FILE *version_file;
 | 
			
		||||
  char version_string[6];
 | 
			
		||||
 | 
			
		||||
  if (!(version_file = fopen("VERSION", "rb"))) {
 | 
			
		||||
    fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__));
 | 
			
		||||
    exit(errno);
 | 
			
		||||
  }
 | 
			
		||||
  fread(version_string, 1, 5, version_file);
 | 
			
		||||
  version_string[5] = '\0';
 | 
			
		||||
  printf("%s\n", version_string);
 | 
			
		||||
  fclose(version_file);
 | 
			
		||||
}
 | 
			
		||||
void version();
 | 
			
		||||
void usage(const char *);
 | 
			
		||||
void draw_greeting();
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
  int option;
 | 
			
		||||
@ -83,31 +56,44 @@ int main(int argc, char *argv[]) {
 | 
			
		||||
  init_pair(3, COLOR_WHITE, COLOR_BLUE);
 | 
			
		||||
  init_pair(4, COLOR_WHITE, COLOR_GREEN);
 | 
			
		||||
 | 
			
		||||
  draw_greeting();
 | 
			
		||||
 | 
			
		||||
  int key;
 | 
			
		||||
  do {
 | 
			
		||||
    switch (key = getch()) {
 | 
			
		||||
    case KEY_SPACEBAR:
 | 
			
		||||
      clear();
 | 
			
		||||
      refresh();
 | 
			
		||||
      game_init(&game, passes_through_deck);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'q':
 | 
			
		||||
    case 'Q':
 | 
			
		||||
 | 
			
		||||
  while (!term_size_ok()) {
 | 
			
		||||
    clear();
 | 
			
		||||
    mvprintw(1, 1, SMALL_TERM_MSG);
 | 
			
		||||
    refresh();
 | 
			
		||||
    if ((key = getch()) == 'q' || key == 'Q') {
 | 
			
		||||
      endwin();
 | 
			
		||||
      return(0);
 | 
			
		||||
    }
 | 
			
		||||
  } while (key != KEY_SPACEBAR);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  do {
 | 
			
		||||
  clear();
 | 
			
		||||
  draw_greeting();
 | 
			
		||||
  refresh();
 | 
			
		||||
 | 
			
		||||
  for (;;) {
 | 
			
		||||
    if ((key = getch()) == 'q' || key == 'Q') {
 | 
			
		||||
      endwin();
 | 
			
		||||
      game_end();
 | 
			
		||||
      exit(0);
 | 
			
		||||
    } else {
 | 
			
		||||
      keyboard_event(key);
 | 
			
		||||
      return(0);
 | 
			
		||||
    }
 | 
			
		||||
    if (term_size_ok()) {
 | 
			
		||||
      clear();
 | 
			
		||||
      draw_greeting();
 | 
			
		||||
      refresh();
 | 
			
		||||
      if (key == KEY_SPACEBAR) {
 | 
			
		||||
        game_init(&game, passes_through_deck);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    } else if (key == KEY_RESIZE) {
 | 
			
		||||
      clear();
 | 
			
		||||
      mvprintw(1, 1, SMALL_TERM_MSG);
 | 
			
		||||
      refresh();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  do {
 | 
			
		||||
    keyboard_event(getch());
 | 
			
		||||
  } while (!game_won());
 | 
			
		||||
 | 
			
		||||
  endwin();
 | 
			
		||||
@ -116,3 +102,32 @@ int main(int argc, char *argv[]) {
 | 
			
		||||
 | 
			
		||||
  return(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_greeting() {
 | 
			
		||||
  mvprintw(8, 26, "Welcome to tty-solitaire.");
 | 
			
		||||
  mvprintw(10, 23, "Move with the arrow keys or hjkl.");
 | 
			
		||||
  mvprintw(11, 19, "Use the space bar to mark and move cards.");
 | 
			
		||||
  mvprintw(12, 16, "After marking a card you can use m to increase ");
 | 
			
		||||
  mvprintw(13, 17, "and n to decrease the number of marked cards.");
 | 
			
		||||
  mvprintw(15, 19, "Press the space bar to play or q to quit.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usage(const char *program_name) {
 | 
			
		||||
  printf("usage: %s [-v|--version] [-h|--help] [-p|--passes=NUMBER]\n", program_name);
 | 
			
		||||
  printf("  -v, --version  Show version\n");
 | 
			
		||||
  printf("  -h, --help     Show this message\n");
 | 
			
		||||
  printf("  -p, --passes   Number of passes through the deck\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void version() {
 | 
			
		||||
  FILE *version_file;
 | 
			
		||||
  char version_string[6];
 | 
			
		||||
 | 
			
		||||
  if (!(version_file = fopen("VERSION", "rb"))) {
 | 
			
		||||
    tty_solitaire_generic_error(errno, __FILE__, __LINE__);
 | 
			
		||||
  }
 | 
			
		||||
  fread(version_string, 1, 5, version_file);
 | 
			
		||||
  version_string[5] = '\0';
 | 
			
		||||
  printf("%s\n", version_string);
 | 
			
		||||
  fclose(version_file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user