From 6d4056875dd3fa29683492bdaf956cd0e893bec6 Mon Sep 17 00:00:00 2001 From: girst Date: Mon, 21 Jan 2019 00:44:15 +0100 Subject: [PATCH] implement restart same game, increase portability, update TODOs * use rand() instead of random() to get in line with mines and viiper * reorder playfield struct for better alignment * remove ignore warnings pragma (not needed any more) * remove _POSIX_C_SOURCE feture test (not needed and breaks freebsd) --- README.md | 13 ++++++++----- sol.c | 33 ++++++++++++++------------------- sol.h | 4 ++-- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index fd15188..242889e 100644 --- a/README.md +++ b/README.md @@ -5,20 +5,19 @@ play klondike and spider solitaire in your unicode terminal. ## TODO ### P1 + * TODO: make portable (clang on FreeBSD) + makefile's `$<` refuses to work if prequisite name != target name ### P2 * TODO: suggest moves (`h` => hint) - * TODO: 'join to here' command (should take longest chain available) * TODO: escape sequences (for real cursor keys) * TODO: inverted moves (if A->B doesn't work, try B->A) * TODO: cleanup: in `x2y()` functions there is a lot of replication and noise when calculating legal moves, top cards, etc. ### P3 - * TODO: screen size > stack height => rendering issues! * TODO: differential drawing mode (at least for highlighting cards) ### P4 * TODO: mouse mode (problems: finding position with `extreme_overlap`) * TODO: scores, variants: draw 3, max. n overturns - * TODO: expose deal() seed for restarting the game * TODO: vt220 mode (problems: charset, slow baudrate and no differential drawing mode) * TODO: ed(1) mode (solEDaire): playable on a line printer; ascii/ibm only? @@ -30,9 +29,9 @@ play klondike and spider solitaire in your unicode terminal. * DONE: patience: allow taking from 0(foundation) * DONE: highlight `from` pile, so users can see at what input stage they are * DONE: make piles 0-indexed in klondike as well - * HOLD: duplicate card ♠A found in tableu: added check at start to monitor this + * DONE: duplicate card ♠A found in tableu: added check at start to monitor this Cannot reproduce, removed check - * HOLD: bugs in spider's t2t() + * DONE: bugs in spider's t2t() * once segfaulted on large column * sometimes doesn't work (ERR when it should be OK) Cannot reproduce @@ -62,6 +61,10 @@ play klondike and spider solitaire in your unicode terminal. already used for closed cards cons: dirty C hack, less obvious than in other places, no need to conserve memory this tightly + * DONE: screen size > stack height => rendering issues! + as good as it's going to get, since we can't just not draw cards at all + * DONE: 'join to here' command (should take longest chain available) + * DONE: expose deal() seed for restarting the game ## Notes diff --git a/sol.c b/sol.c index aa32861..1e49d4c 100644 --- a/sol.c +++ b/sol.c @@ -1,5 +1,4 @@ -#define _DEFAULT_SOURCE -#define _POSIX_C_SOURCE /* for sigaction */ +#define _DEFAULT_SOURCE /* for getopt, sigaction, usleep */ #include #include #include @@ -98,10 +97,10 @@ newgame: } int sol(void) { - /* clean undo (from previous game): */ + long seed = time(NULL); +restart: free_undo(f.u); - - deal(); + deal(seed); int from, to, opt; for(;;) { @@ -109,11 +108,10 @@ int sol(void) { case CMD_MOVE: switch (action[from][to](from,to,opt)) { case OK: break; - case ERR: visbell(); break; + case ERR: visbell(); break; //TODO: try again with from/to swapped case WON: return GAME_WON; } break; - case CMD_HINT: break;//TODO: show a possible (and sensible) move. if possible, involve active cursor case CMD_JOIN: switch (join(to)) { case OK: break; @@ -121,10 +119,11 @@ int sol(void) { case WON: return GAME_WON; } break; - case CMD_UNDO: undo_pop(f.u); break; + case CMD_HINT: break;//TODO: show a possible (and sensible) move. if possible, involve active cursor + case CMD_UNDO: undo_pop(f.u); break; case CMD_INVAL: visbell(); break; case CMD_NEW: return GAME_NEW; - case CMD_AGAIN: //TODO: restart with same seed + case CMD_AGAIN: goto restart; case CMD_QUIT: return GAME_QUIT; } } @@ -462,7 +461,6 @@ int nop(int from, int to, int opt) { (void)from;(void)to;(void)opt;return ERR; } // keyboard input handling {{{ // cursor functions{{{ -#pragma GCC diagnostic ignored "-Wswitch" //not ideal :| #ifdef KLONDIKE void cursor_left (struct cursor* cursor) { if (is_tableu(cursor->pile)) { @@ -540,7 +538,6 @@ void cursor_to (struct cursor* cursor, int pile) { cursor->pile = pile; cursor->opt = 0; } -#pragma GCC diagnostic pop //}}} int get_cmd (int* from, int* to, int* opt) { //TODO: escape sequences (mouse, cursor keys) @@ -715,7 +712,7 @@ to_l: print_table(&active, &inactive); // }}} // shuffling and dealing {{{ -void deal(void) { +void deal(long seed) { f = (const struct playfield){0}; /* clear playfield */ card_t deck[DECK_SIZE*NUM_DECKS]; int avail = DECK_SIZE*NUM_DECKS; @@ -727,11 +724,9 @@ void deal(void) { /* the 1+ -1 dance gets rid of the offset created by NO_CARD */ } #endif - srandom (time(NULL)); - long seed = time(NULL); - srandom (seed); + srand (seed); for (int i = DECK_SIZE*NUM_DECKS-1; i > 0; i--) { /* fisher-yates */ - int j = random() % (i+1); + int j = rand() % (i+1); if (j-i) deck[i]^=deck[j],deck[j]^=deck[i],deck[i]^=deck[j]; } @@ -902,11 +897,11 @@ void win_anim(void) { printf ("\033[?25l"); /* hide cursor */ for (;;) { /* set cursor to random location */ - int row = 1+random()%(24-op.s->width); - int col = 1+random()%(80-op.s->height); + int row = 1+rand()%(24-op.s->width); + int col = 1+rand()%(80-op.s->height); /* draw random card */ - int face = 1 + random() % 52; + int face = 1 + rand() % 52; for (int l = 0; l < op.s->height; l++) { printf ("\033[%d;%dH", row+l, col); printf ("%s", op.s->card[face][l]); diff --git a/sol.h b/sol.h index be16dfe..e40a20b 100644 --- a/sol.h +++ b/sol.h @@ -121,9 +121,9 @@ enum difficulty { typedef signed char card_t; struct playfield { - card_t s[MAX_STOCK]; /* stock */ int z; /* stock size */ int w; /* waste; index into stock (occupied foundations in spider) */ + card_t s[MAX_STOCK]; /* stock */ card_t f[NUM_DECKS*NUM_SUITS][PILE_SIZE]; /* foundation */ card_t t[NUM_PILES][PILE_SIZE]; /* tableu piles */ struct undo { @@ -217,7 +217,7 @@ void cursor_down (struct cursor* cursor); void cursor_up (struct cursor* cursor); void cursor_right (struct cursor* cursor); int get_cmd (int* from, int* to, int* opt); -void deal(void); +void deal(long seed); void print_hi(int invert, int grey_bg, int bold, char* str); void print_table(const struct cursor* active, const struct cursor* inactive); void visbell (void); -- 2.39.3