From 9812b32a536a0b7f7fa8d4d7ecda57219ba1bb7d Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Mon, 28 Nov 1994 23:18:07 +0000 Subject: [PATCH] Initial revision --- bluemoon.c | 573 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 573 insertions(+) create mode 100644 bluemoon.c diff --git a/bluemoon.c b/bluemoon.c new file mode 100644 index 0000000..8f06604 --- /dev/null +++ b/bluemoon.c @@ -0,0 +1,573 @@ +/***************************************************************************** + * * + * B l u e M o o n * + * ================= * + * V2.1 * + * A patience game by T.A.Lister * + * Integral screen support by Eric S. Raymond * + * * + *****************************************************************************/ + +/* + * Compile this with the command `cc -O blue.c -ltermcap -o blue`. You might + * have to plug in a different library name for -ltermcap; -lcurses and + * -ltermlib are common alternatives. + * + * If your terminal type has IBMPREFIX as a prefix, this program will assume + * your terminal can display the IBM card-suit graphics using the strings given + * here. These strings work with the generic AT&T System V console(7) driver + * on AT-compatible boxes; if you have something else (like a pre-merge XENIX) + * they might have to change. This ugly kluge is needed because as of SVr3.2 + * termcap/terminfo doesn't yet have a capability for displaying the `literal' + * values of control characters. + * + * Warning: due to a bug in tgetent() on the 6386WGS (and possibly elsewhere) + * under SVr3.2, running this program may trash eof, tab3 and possibly other + * pieces of your tty control info. If this happens, recompile with -DBROKEN. + */ +#define IBMPREFIX "AT" +#define HEART "\033[11m\003\033[10m" +#define SPADE "\033[11m\006\033[10m" +#define DIAMOND "\033[11m\004\033[10m" +#define CLUB "\033[11m\005\033[10m" + +#include +#include +#include /* for isdigit() */ +#ifdef BROKEN +#include + +static struct termio savetty; +#endif /* BROKEN */ + +extern long time(); +extern char *malloc(); + +#define NOCARD (-1) + +#define ACE 0 +#define KING 12 +#define SUIT_LENGTH 13 + +#define HEARTS 0 +#define SPADES 1 +#define DIAMONDS 2 +#define CLUBS 3 +#define NSUITS 4 + +#define GRID_WIDTH 14 /* 13+1 */ +#define GRID_LENGTH 56 /* 4*(13+1) */ +#define PACK_SIZE 52 + +#define BASEROW 1 +#define PROMPTROW 11 + +/* these are the terminfo indexes for the basic colors it guarantees */ +#define COLOR_BLACK 0 +#define COLOR_BLUE 1 +#define COLOR_GREEN 2 +#define COLOR_CYAN 3 +#define COLOR_RED 4 +#define COLOR_MAGENTA 5 +#define COLOR_YELLOW 6 +#define COLOR_WHITE 7 + +static int deck_size = PACK_SIZE; /* initial deck */ +static int deck[PACK_SIZE]; + +static int grid[GRID_LENGTH]; /* card layout grid */ +static int freeptr[4]; /* free card space pointers */ + +static int deal_number=0; + +static char *suits[] = {"h", "s", "d", "c" }; + +/* + * Here goes the screen support. We don't use terminfo/termcap because of + * the incredible braindamage they manifest when you try to output control + * characters -- on IBM-compatible machines this leads to serious lossage. + * + * The only functions this code requires from curses(3) are: + * + * cbreak(), nocbreak(), tgetstr(), tgetnum(), tputs(), tparm(), tgoto() + * + * so a port to MS-DOS using PC-Curses or some variant thereof ought to be + * fairly easy. + */ + +static int CO, LI; +static char *HO, *CL, *CM, *CE, *SO, *SE, *VS, *VE, *HI, *HE, *SF, *SB; + +/* lowest-level character output */ + +static void xputc(c) +char c; +{ + putchar(c); +} + +void xputs(s) +char *s; +{ + tputs(s, 1, (int (*)())xputc); +} + +static void initscr() +{ + extern char *tgetstr(); + extern char *tparm(), *tgetstr(); + extern char *getenv(); + extern int tgetnum(); + void clear(); + + register char *term; + register char *tptr; + register int i; + + if((term = getenv("TERM")) == (char *)NULL) + { + (void) fprintf(stderr, "Can't get TERM.\n"); + exit(1); + } + + tptr = malloc(10000); + if (tgetent(tptr, term) < 1) + { + (void) fprintf(stderr, "Unknown terminal type: %s.\n", term); + exit(1); + } + + HO = tgetstr("ho", (char *)NULL); + CO = tgetnum("co"); + LI = tgetnum("li"); + if(!(CL = tgetstr("cl", (char *)NULL)) || !(CM = tgetstr("cm", (char *)NULL))) + { + (void) fprintf(stderr, "Blue needs CL and CM\n"); + exit(1); + } + CE = tgetstr("ce", (char *)NULL); + SO = tgetstr("so", (char *)NULL); + SE = tgetstr("se", (char *)NULL); + VS = tgetstr("vs", (char *)NULL); + VE = tgetstr("ve", (char *)NULL); + HI = tgetstr("hi", (char *)NULL); + HE = tgetstr("he", (char *)NULL); + SF = SB = ""; + if (tgetnum("Co") >= 8) + { + SF = tgetstr("Sf", (char *)NULL); + SB = tgetstr("Sb", (char *)NULL); + } + + free(tptr); + + if (strncmp(term, IBMPREFIX, sizeof(IBMPREFIX) - 1) == 0) + { + suits[HEARTS] = HEART; + suits[SPADES] = SPADE; + suits[DIAMONDS] = DIAMOND; + suits[CLUBS] = CLUB; + } + + tputs(VS); +} + +static void endwin() +{ + xputs(VE); +} + +/* Cursor movements */ + +static void home() +{ + if(HO) + xputs(HO); + else + xputs(tgoto(CM, 0, 0)); +} + +static void clear() +{ + xputs(CL); + home(); +} + +static void clrtoeol() +{ + xputs(CE); +} + +static void refresh() +{ + (void) fflush(stdout); +} + +static void move(y, x) +register int y, x; +{ + xputs(tgoto(CM, x - 1, y - 1)); +} + +static void standout() +{ + if(SO) xputs(SO); +} + +static void standend() +{ + if(SE) xputs(SE); +} + +static void setfore(color) +int color; +{ + extern char *tparm(); + + if (SF) + xputs(tparm(SF, color)); +} + +static void setback(color) +int color; +{ + extern char *tparm(); + + if (SB) + xputs(tparm(SB, color)); +} + +/* + * OK, here is the game proper + */ + +static void die(onsig) +int onsig; +{ + signal(SIGINT, SIG_IGN); + setfore(COLOR_WHITE); + setback(COLOR_BLACK); + if (onsig) + clear(); + endwin(); +#ifdef BSD + nocrmode(); +#else + nocbreak(); +#endif /* BSD */ +#ifdef BROKEN + (void) ioctl(0, TCSETA, &savetty); +#endif /* BROKEN */ + exit(0); +} + +static void init_vars() +{ + int i; + + deck_size=PACK_SIZE; + for(i=0;i=PACK_SIZE)) return NOCARD; + for(i=0;i'd') && (c!='r') && (c!='q')); + } + + for (j = 0; j < 4; j++) + if (select[j]!=NOCARD) + { + move(BASEROW + (select[j] / GRID_WIDTH)*2+3, + (select[j] % GRID_WIDTH)*5); + (void)printf(" "); + } + + if (c == 'r') + display_cards(deal_number); + else if (c == 'q') + die(0); + else + { + i = c-'a'; + if (select[i] == NOCARD) + (void) putchar('\007'); + else + { + movecard(select[i], freeptr[i]); + freeptr[i]=select[i]; + } + } + } + } + + move(PROMPTROW, 0); + standout(); + (void)printf("Finished deal %d - type any character to continue...", deal_number); + standend(); + (void) getchar(); +} + +static int collect_discards() +{ + int row, col, cardno=0, finish, gridno; + + for (row=HEARTS;row<=CLUBS;row++) + { + finish=0; + for (col=1;col