Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 1 | /**************************************************************************** |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 2 | * Copyright 2019-2021,2022 Thomas E. Dickey * |
| 3 | * Copyright 1998-2016,2017 Free Software Foundation, Inc. * |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 4 | * * |
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a * |
| 6 | * copy of this software and associated documentation files (the * |
| 7 | * "Software"), to deal in the Software without restriction, including * |
| 8 | * without limitation the rights to use, copy, modify, merge, publish, * |
| 9 | * distribute, distribute with modifications, sublicense, and/or sell * |
| 10 | * copies of the Software, and to permit persons to whom the Software is * |
| 11 | * furnished to do so, subject to the following conditions: * |
| 12 | * * |
| 13 | * The above copyright notice and this permission notice shall be included * |
| 14 | * in all copies or substantial portions of the Software. * |
| 15 | * * |
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * |
| 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * |
| 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * |
| 19 | * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * |
| 20 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * |
| 21 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * |
| 22 | * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * |
| 23 | * * |
| 24 | * Except as contained in this notice, the name(s) of the above copyright * |
| 25 | * holders shall not be used in advertising or otherwise to promote the * |
| 26 | * sale, use or other dealings in this Software without prior written * |
| 27 | * authorization. * |
| 28 | ****************************************************************************/ |
| 29 | /***************************************************************************** |
| 30 | * * |
| 31 | * B l u e M o o n * |
| 32 | * ================= * |
| 33 | * V2.2 * |
| 34 | * A patience game by T.A.Lister * |
| 35 | * Integral screen support by Eric S. Raymond * |
| 36 | * * |
| 37 | *****************************************************************************/ |
| 38 | |
| 39 | /* |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 40 | * $Id: blue.c,v 1.55 2022/12/10 23:31:31 tom Exp $ |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 41 | */ |
| 42 | |
| 43 | #include <test.priv.h> |
| 44 | |
| 45 | #include <time.h> |
| 46 | |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 47 | #if HAVE_LANGINFO_CODESET |
| 48 | #include <langinfo.h> |
| 49 | #endif |
| 50 | |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 51 | #define NOCARD (-1) |
| 52 | |
| 53 | #define ACE 0 |
| 54 | #define KING 12 |
| 55 | #define SUIT_LENGTH 13 |
| 56 | |
| 57 | #define HEARTS 0 |
| 58 | #define SPADES 1 |
| 59 | #define DIAMONDS 2 |
| 60 | #define CLUBS 3 |
| 61 | #define NSUITS 4 |
| 62 | |
| 63 | #define GRID_WIDTH 14 /* 13+1 */ |
| 64 | #define GRID_LENGTH 56 /* 4*(13+1) */ |
| 65 | #define PACK_SIZE 52 |
| 66 | |
| 67 | #define BASEROW 1 |
| 68 | #define PROMPTROW 11 |
| 69 | |
| 70 | #define RED_ON_WHITE 1 |
| 71 | #define BLACK_ON_WHITE 2 |
| 72 | #define BLUE_ON_WHITE 3 |
| 73 | |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 74 | static GCC_NORETURN void die(int onsig); |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 75 | |
| 76 | static int deck_size = PACK_SIZE; /* initial deck */ |
| 77 | static int deck[PACK_SIZE]; |
| 78 | |
| 79 | static int grid[GRID_LENGTH]; /* card layout grid */ |
| 80 | static int freeptr[4]; /* free card space pointers */ |
| 81 | |
| 82 | static int deal_number = 0; |
| 83 | |
| 84 | static chtype ranks[SUIT_LENGTH][2] = |
| 85 | { |
| 86 | {' ', 'A'}, |
| 87 | {' ', '2'}, |
| 88 | {' ', '3'}, |
| 89 | {' ', '4'}, |
| 90 | {' ', '5'}, |
| 91 | {' ', '6'}, |
| 92 | {' ', '7'}, |
| 93 | {' ', '8'}, |
| 94 | {' ', '9'}, |
| 95 | {'1', '0'}, |
| 96 | {' ', 'J'}, |
| 97 | {' ', 'Q'}, |
| 98 | {' ', 'K'} |
| 99 | }; |
| 100 | |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 101 | static int letters[4] = |
| 102 | { |
| 103 | 'h', /* hearts */ |
| 104 | 's', /* spades */ |
| 105 | 'd', /* diamonds */ |
| 106 | 'c', /* clubs */ |
| 107 | }; |
| 108 | |
| 109 | #if HAVE_LANGINFO_CODESET |
| 110 | |
| 111 | #if HAVE_TIGETSTR |
| 112 | static int glyphs[] = |
| 113 | { |
| 114 | '\003', /* hearts */ |
| 115 | '\006', /* spades */ |
| 116 | '\004', /* diamonds */ |
| 117 | '\005', /* clubs */ |
| 118 | }; |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 119 | #endif |
| 120 | |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 121 | #if USE_WIDEC_SUPPORT |
| 122 | static int uglyphs[] = |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 123 | { |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 124 | 0x2665, /* hearts */ |
| 125 | 0x2660, /* spades */ |
| 126 | 0x2666, /* diamonds */ |
| 127 | 0x2663 /* clubs */ |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 128 | }; |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 129 | #endif |
| 130 | #endif /* HAVE_LANGINFO_CODESET */ |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 131 | |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 132 | static int *suits = letters; /* this may change to glyphs below */ |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 133 | |
| 134 | static void |
| 135 | die(int onsig) |
| 136 | { |
| 137 | (void) signal(onsig, SIG_IGN); |
| 138 | endwin(); |
| 139 | ExitProgram(EXIT_SUCCESS); |
| 140 | } |
| 141 | |
| 142 | static void |
| 143 | init_vars(void) |
| 144 | { |
| 145 | int i; |
| 146 | |
| 147 | deck_size = PACK_SIZE; |
| 148 | for (i = 0; i < PACK_SIZE; i++) |
| 149 | deck[i] = i; |
| 150 | for (i = 0; i < 4; i++) |
| 151 | freeptr[i] = i * GRID_WIDTH; |
| 152 | } |
| 153 | |
| 154 | static void |
| 155 | shuffle(int size) |
| 156 | { |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 157 | int numswaps, swapnum; |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 158 | |
| 159 | numswaps = size * 10; /* an arbitrary figure */ |
| 160 | |
| 161 | for (swapnum = 0; swapnum < numswaps; swapnum++) { |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 162 | int i = rand() % size; |
| 163 | int j = rand() % size; |
| 164 | int temp = deck[i]; |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 165 | deck[i] = deck[j]; |
| 166 | deck[j] = temp; |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | static void |
| 171 | deal_cards(void) |
| 172 | { |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 173 | int card = 0, value, csuit, crank, suit, aces[4]; |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 174 | |
| 175 | memset(aces, 0, sizeof(aces)); |
| 176 | for (suit = HEARTS; suit <= CLUBS; suit++) { |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 177 | int ptr = freeptr[suit]; |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 178 | grid[ptr++] = NOCARD; /* 1st card space is blank */ |
| 179 | while ((ptr % GRID_WIDTH) != 0) { |
| 180 | value = deck[card++]; |
| 181 | crank = value % SUIT_LENGTH; |
| 182 | csuit = value / SUIT_LENGTH; |
| 183 | if (crank == ACE) |
| 184 | aces[csuit] = ptr; |
| 185 | grid[ptr++] = value; |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | if (deal_number == 1) /* shift the aces down to the 1st column */ |
| 190 | for (suit = HEARTS; suit <= CLUBS; suit++) { |
| 191 | grid[suit * GRID_WIDTH] = suit * SUIT_LENGTH; |
| 192 | grid[aces[suit]] = NOCARD; |
| 193 | freeptr[suit] = aces[suit]; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | static void |
| 198 | printcard(int value) |
| 199 | { |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 200 | AddCh(' '); |
| 201 | if (value == NOCARD) { |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 202 | (void) addstr(" "); |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 203 | } else { |
| 204 | int which = (value / SUIT_LENGTH); |
| 205 | int isuit = (value % SUIT_LENGTH); |
| 206 | chtype color = (chtype) COLOR_PAIR(((which % 2) == 0) |
| 207 | ? RED_ON_WHITE |
| 208 | : BLACK_ON_WHITE); |
| 209 | |
| 210 | AddCh(ranks[isuit][0] | (chtype) COLOR_PAIR(BLUE_ON_WHITE)); |
| 211 | AddCh(ranks[isuit][1] | (chtype) COLOR_PAIR(BLUE_ON_WHITE)); |
| 212 | |
| 213 | #ifdef NCURSES_VERSION |
| 214 | (attron) ((int) color); /* quieter compiler warnings */ |
| 215 | #else |
| 216 | attron(color); /* PDCurses, etc., either no macro or wrong */ |
| 217 | #endif |
| 218 | #if USE_WIDEC_SUPPORT |
| 219 | { |
| 220 | wchar_t values[2]; |
| 221 | values[0] = (wchar_t) suits[which]; |
| 222 | values[1] = 0; |
| 223 | addwstr(values); |
| 224 | } |
| 225 | #else |
| 226 | AddCh(suits[which]); |
| 227 | #endif |
| 228 | #ifdef NCURSES_VERSION |
| 229 | (attroff) ((int) color); |
| 230 | #else |
| 231 | attroff(color); |
| 232 | #endif |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 233 | } |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 234 | AddCh(' '); |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 235 | } |
| 236 | |
| 237 | static void |
| 238 | display_cards(int deal) |
| 239 | { |
| 240 | int row, card; |
| 241 | |
| 242 | clear(); |
| 243 | (void) printw( |
| 244 | "Blue Moon 2.1 - by Tim Lister & Eric Raymond - Deal %d.\n", |
| 245 | deal); |
| 246 | for (row = HEARTS; row <= CLUBS; row++) { |
| 247 | move(BASEROW + row + row + 2, 1); |
| 248 | for (card = 0; card < GRID_WIDTH; card++) |
| 249 | printcard(grid[row * GRID_WIDTH + card]); |
| 250 | } |
| 251 | |
| 252 | move(PROMPTROW + 2, 0); |
| 253 | refresh(); |
| 254 | #define P(x) (void)printw("%s\n", x) |
| 255 | P(" This 52-card solitaire starts with the entire deck shuffled and dealt"); |
| 256 | P("out in four rows. The aces are then moved to the left end of the layout,"); |
| 257 | P("making 4 initial free spaces. You may move to a space only the card that"); |
| 258 | P("matches the left neighbor in suit, and is one greater in rank. Kings are"); |
| 259 | P("high, so no cards may be placed to their right (they create dead spaces)."); |
| 260 | P(" When no moves can be made, cards still out of sequence are reshuffled"); |
| 261 | P("and dealt face up after the ends of the partial sequences, leaving a card"); |
| 262 | P("space after each sequence, so that each row looks like a partial sequence"); |
| 263 | P("followed by a space, followed by enough cards to make a row of 14. "); |
| 264 | P(" A moment's reflection will show that this game cannot take more than 13"); |
| 265 | P("deals. A good score is 1-3 deals, 4-7 is average, 8 or more is poor. "); |
| 266 | #undef P |
| 267 | refresh(); |
| 268 | } |
| 269 | |
| 270 | static int |
| 271 | find(int card) |
| 272 | { |
| 273 | int i; |
| 274 | |
| 275 | if ((card < 0) || (card >= PACK_SIZE)) |
| 276 | return (NOCARD); |
| 277 | for (i = 0; i < GRID_LENGTH; i++) |
| 278 | if (grid[i] == card) |
| 279 | return i; |
| 280 | return (NOCARD); |
| 281 | } |
| 282 | |
| 283 | static void |
| 284 | movecard(int src, int dst) |
| 285 | { |
| 286 | grid[dst] = grid[src]; |
| 287 | grid[src] = NOCARD; |
| 288 | |
| 289 | move(BASEROW + (dst / GRID_WIDTH) * 2 + 2, (dst % GRID_WIDTH) * 5 + 1); |
| 290 | printcard(grid[dst]); |
| 291 | |
| 292 | move(BASEROW + (src / GRID_WIDTH) * 2 + 2, (src % GRID_WIDTH) * 5 + 1); |
| 293 | printcard(grid[src]); |
| 294 | |
| 295 | refresh(); |
| 296 | } |
| 297 | |
| 298 | static void |
| 299 | play_game(void) |
| 300 | { |
| 301 | int dead = 0, i, j; |
| 302 | char c; |
| 303 | int selection[4], card; |
| 304 | |
| 305 | while (dead < 4) { |
| 306 | dead = 0; |
| 307 | for (i = 0; i < 4; i++) { |
| 308 | card = grid[freeptr[i] - 1]; |
| 309 | |
| 310 | if (((card % SUIT_LENGTH) == KING) |
| 311 | || |
| 312 | (card == NOCARD)) |
| 313 | selection[i] = NOCARD; |
| 314 | else |
| 315 | selection[i] = find(card + 1); |
| 316 | |
| 317 | if (selection[i] == NOCARD) |
| 318 | dead++; |
| 319 | }; |
| 320 | |
| 321 | if (dead < 4) { |
| 322 | char live[NSUITS + 1], *lp = live; |
| 323 | |
| 324 | for (i = 0; i < 4; i++) { |
| 325 | if (selection[i] != NOCARD) { |
| 326 | move(BASEROW + (selection[i] / GRID_WIDTH) * 2 + 3, |
| 327 | (selection[i] % GRID_WIDTH) * 5); |
| 328 | (void) printw(" %c ", (*lp++ = (char) ('a' + i))); |
| 329 | } |
| 330 | }; |
| 331 | *lp = '\0'; |
| 332 | |
| 333 | if (strlen(live) == 1) { |
| 334 | move(PROMPTROW, 0); |
| 335 | (void) printw( |
| 336 | "Making forced moves... "); |
| 337 | refresh(); |
| 338 | (void) sleep(1); |
| 339 | c = live[0]; |
| 340 | } else { |
| 341 | char buf[BUFSIZ]; |
| 342 | |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 343 | _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) |
| 344 | "Type [%s] to move, r to redraw, q or INTR to quit: ", |
| 345 | live); |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 346 | |
| 347 | do { |
| 348 | move(PROMPTROW, 0); |
| 349 | (void) addstr(buf); |
| 350 | move(PROMPTROW, (int) strlen(buf)); |
| 351 | clrtoeol(); |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 352 | AddCh(' '); |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 353 | } while |
| 354 | (((c = (char) getch()) < 'a' || c > 'd') |
| 355 | && (c != 'r') |
| 356 | && (c != 'q')); |
| 357 | } |
| 358 | |
| 359 | for (j = 0; j < 4; j++) |
| 360 | if (selection[j] != NOCARD) { |
| 361 | move(BASEROW + (selection[j] / GRID_WIDTH) * 2 + 3, |
| 362 | (selection[j] % GRID_WIDTH) * 5); |
| 363 | (void) printw(" "); |
| 364 | } |
| 365 | |
| 366 | if (c == 'r') |
| 367 | display_cards(deal_number); |
| 368 | else if (c == 'q') |
| 369 | die(SIGINT); |
| 370 | else { |
| 371 | i = c - 'a'; |
| 372 | if (selection[i] == NOCARD) |
| 373 | beep(); |
| 374 | else { |
| 375 | movecard(selection[i], freeptr[i]); |
| 376 | freeptr[i] = selection[i]; |
| 377 | } |
| 378 | } |
| 379 | } |
| 380 | } |
| 381 | |
| 382 | move(PROMPTROW, 0); |
| 383 | (void) standout(); |
| 384 | (void) printw("Finished deal %d - type any character to continue...", deal_number); |
| 385 | (void) standend(); |
| 386 | (void) getch(); |
| 387 | } |
| 388 | |
| 389 | static int |
| 390 | collect_discards(void) |
| 391 | { |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 392 | int row, col, cardno = 0, gridno; |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 393 | |
| 394 | for (row = HEARTS; row <= CLUBS; row++) { |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 395 | int finish = 0; |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 396 | for (col = 1; col < GRID_WIDTH; col++) { |
| 397 | gridno = row * GRID_WIDTH + col; |
| 398 | |
| 399 | if ((grid[gridno] != (grid[gridno - 1] + 1)) && (finish == 0)) { |
| 400 | finish = 1; |
| 401 | freeptr[row] = gridno; |
| 402 | }; |
| 403 | |
| 404 | if ((finish != 0) && (grid[gridno] != NOCARD)) |
| 405 | deck[cardno++] = grid[gridno]; |
| 406 | } |
| 407 | } |
| 408 | return cardno; |
| 409 | } |
| 410 | |
| 411 | static void |
| 412 | game_finished(int deal) |
| 413 | { |
| 414 | clear(); |
| 415 | (void) printw("You finished the game in %d deals. This is ", deal); |
| 416 | (void) standout(); |
| 417 | if (deal < 2) |
| 418 | (void) addstr("excellent"); |
| 419 | else if (deal < 4) |
| 420 | (void) addstr("good"); |
| 421 | else if (deal < 8) |
| 422 | (void) addstr("average"); |
| 423 | else |
| 424 | (void) addstr("poor"); |
| 425 | (void) standend(); |
| 426 | (void) addstr(". "); |
| 427 | refresh(); |
| 428 | } |
| 429 | |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 430 | #if HAVE_LANGINFO_CODESET |
| 431 | /* |
| 432 | * This program first appeared in ncurses in January 1995. At that point, the |
| 433 | * Linux console was able to display CP437 graphic characters, e.g., in the |
| 434 | * range 0-31. As of 2016, most Linux consoles are running with the UTF-8 |
| 435 | * (partial) support. Incidentally, that makes all of the cards diamonds. |
| 436 | */ |
| 437 | static void |
| 438 | use_pc_display(void) |
| 439 | { |
| 440 | char *check = nl_langinfo(CODESET); |
| 441 | if (!strcmp(check, "UTF-8")) { |
| 442 | #if USE_WIDEC_SUPPORT |
| 443 | suits = uglyphs; |
| 444 | #endif |
| 445 | } else { |
| 446 | #if HAVE_TIGETSTR |
| 447 | if (!strcmp(check, "IBM437") || |
| 448 | !strcmp(check, "CP437") || |
| 449 | !strcmp(check, "IBM850") || |
| 450 | !strcmp(check, "CP850")) { |
| 451 | char *smacs = tigetstr("smacs"); |
| 452 | char *smpch = tigetstr("smpch"); |
| 453 | /* |
| 454 | * The ncurses library makes this check to decide whether to allow |
| 455 | * the alternate character set for the (normally) nonprinting codes. |
| 456 | */ |
| 457 | if (smacs != 0 && smpch != 0 && !strcmp(smacs, smpch)) { |
| 458 | suits = glyphs; |
| 459 | } |
| 460 | } |
| 461 | #endif |
| 462 | } |
| 463 | } |
| 464 | #else |
| 465 | #define use_pc_display() /* nothing */ |
| 466 | #endif /* HAVE_LANGINFO_CODESET */ |
| 467 | |
| 468 | static void |
| 469 | usage(int ok) |
| 470 | { |
| 471 | static const char *msg[] = |
| 472 | { |
| 473 | "Usage: blue [options]" |
| 474 | ,"" |
| 475 | ,USAGE_COMMON |
| 476 | }; |
| 477 | size_t n; |
| 478 | |
| 479 | for (n = 0; n < SIZEOF(msg); n++) |
| 480 | fprintf(stderr, "%s\n", msg[n]); |
| 481 | |
| 482 | ExitProgram(ok ? EXIT_SUCCESS : EXIT_FAILURE); |
| 483 | } |
| 484 | /* *INDENT-OFF* */ |
| 485 | VERSION_COMMON() |
| 486 | /* *INDENT-ON* */ |
| 487 | |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 488 | int |
| 489 | main(int argc, char *argv[]) |
| 490 | { |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 491 | int ch; |
| 492 | |
| 493 | while ((ch = getopt(argc, argv, OPTS_COMMON)) != -1) { |
| 494 | switch (ch) { |
| 495 | case OPTS_VERSION: |
| 496 | show_version(argv); |
| 497 | ExitProgram(EXIT_SUCCESS); |
| 498 | default: |
| 499 | usage(ch == OPTS_USAGE); |
| 500 | /* NOTREACHED */ |
| 501 | } |
| 502 | } |
| 503 | if (optind < argc) |
| 504 | usage(FALSE); |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 505 | |
| 506 | setlocale(LC_ALL, ""); |
| 507 | |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 508 | use_pc_display(); |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 509 | |
micky387 | 9b9f5e7 | 2025-07-08 18:04:53 -0400 | [diff] [blame] | 510 | InitAndCatch(initscr(), die); |
| 511 | |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 512 | start_color(); |
| 513 | init_pair(RED_ON_WHITE, COLOR_RED, COLOR_WHITE); |
| 514 | init_pair(BLUE_ON_WHITE, COLOR_BLUE, COLOR_WHITE); |
| 515 | init_pair(BLACK_ON_WHITE, COLOR_BLACK, COLOR_WHITE); |
| 516 | |
Steve Kondik | ae271bc | 2015-11-15 02:50:53 +0100 | [diff] [blame] | 517 | cbreak(); |
| 518 | |
| 519 | if (argc == 2) |
| 520 | srand((unsigned) atoi(argv[1])); |
| 521 | else |
| 522 | srand((unsigned) time((time_t *) 0)); |
| 523 | |
| 524 | init_vars(); |
| 525 | |
| 526 | do { |
| 527 | deal_number++; |
| 528 | shuffle(deck_size); |
| 529 | deal_cards(); |
| 530 | display_cards(deal_number); |
| 531 | play_game(); |
| 532 | } |
| 533 | while |
| 534 | ((deck_size = collect_discards()) != 0); |
| 535 | |
| 536 | game_finished(deal_number); |
| 537 | |
| 538 | die(SIGINT); |
| 539 | /*NOTREACHED */ |
| 540 | } |
| 541 | |
| 542 | /* blue.c ends here */ |