* *
* B l u e M o o n *
* ================= *
- * V2.1 *
+ * V2.2 *
* 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.
+ * Compile this with the command `cc -O blue.c -lcurses -o blue'. For best
+ * results, use the portable freeware ncurses(3) library. On non-Intel
+ * machines, SVr4 curses is just as good.
*/
-#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 <signal.h>
-#include <stdio.h>
-#include <ctype.h> /* for isdigit() */
-#ifdef BROKEN
-#include <termio.h>
-
-static struct termio savetty;
-#endif /* BROKEN */
-
-extern long time();
-extern char *malloc();
+#include <curses.h>
#define NOCARD (-1)
#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 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 char *ranks[SUIT_LENGTH] =
+ {" A"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10"," J"," Q"," K"};
-static void setfore(color)
-int color;
+static chtype letters[] =
{
- extern char *tparm();
-
- if (SF)
- xputs(tparm(SF, color));
-}
-
-static void setback(color)
-int color;
+ 'h' | COLOR_PAIR(COLOR_RED), /* hearts */
+ 's' | A_REVERSE, /* spades */
+ 'd' | COLOR_PAIR(COLOR_RED), /* diamonds */
+ 'c' | A_REVERSE, /* clubs */
+};
+
+#if defined(__i386__) && defined(A_PCCHARSET)
+static chtype glyphs[] =
{
- extern char *tparm();
-
- if (SB)
- xputs(tparm(SB, color));
-}
+ '\003' | A_PCCHARSET | COLOR_PAIR(COLOR_RED), /* hearts */
+ '\006' | A_PCCHARSET | A_REVERSE, /* spades */
+ '\004' | A_PCCHARSET | COLOR_PAIR(COLOR_RED), /* diamonds */
+ '\005' | A_PCCHARSET | A_REVERSE, /* clubs */
+};
+#endif /* __i386__ && A_PCCHARSET */
-/*
- * OK, here is the game proper
- */
+static chtype *suits = letters; /* this may change to glyphs below */
static void die(onsig)
int onsig;
{
- signal(SIGINT, SIG_IGN);
- setfore(COLOR_WHITE);
- setback(COLOR_BLACK);
- if (onsig)
- clear();
+ signal(onsig, SIG_IGN);
endwin();
-#ifdef BSD
- nocrmode();
-#else
- nocbreak();
-#endif /* BSD */
-#ifdef BROKEN
- (void) ioctl(0, TCSETA, &savetty);
-#endif /* BROKEN */
exit(0);
}
static void shuffle(size)
int size;
{
- int i,j,numswaps,swapnum,temp;
+ int i,j,numswaps,swapnum,temp;
- numswaps=size*10; /* an arbitrary figure */
+ numswaps=size*10; /* an arbitrary figure */
- for (swapnum=0;swapnum<numswaps;swapnum++)
- {
- i=rand() % size;
- j=rand() % size;
- temp=deck[i];
- deck[i]=deck[j];
- deck[j]=temp;
- }
+ for (swapnum=0;swapnum<numswaps;swapnum++)
+ {
+ i=rand() % size;
+ j=rand() % size;
+ temp=deck[i];
+ deck[i]=deck[j];
+ deck[j]=temp;
+ }
}
static void deal_cards()
static void printcard(value)
int value;
{
- static char *ranks[SUIT_LENGTH] =
- {" A"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10"," J"," Q"," K"};
-
- (void)putchar(' ');
+ (void) addch(' ');
if (value == NOCARD)
- (void)printf(" ");
+ (void) addstr(" ");
else
{
- setback(COLOR_WHITE);
- setfore(COLOR_BLUE);
- xputs(ranks[value % SUIT_LENGTH]);
- setfore((value / SUIT_LENGTH) % 2 ? COLOR_BLACK : COLOR_RED);
- xputs(suits[value / SUIT_LENGTH]);
- setfore(COLOR_WHITE);
- setback(COLOR_BLACK);
+ addch(ranks[value % SUIT_LENGTH][0] | COLOR_PAIR(COLOR_BLUE));
+ addch(ranks[value % SUIT_LENGTH][1] | COLOR_PAIR(COLOR_BLUE));
+ addch(suits[value / SUIT_LENGTH]);
}
- (void)putchar(' ');
+ (void) addch(' ');
}
static void display_cards(deal)
int row, card;
clear();
- (void)printf(
+ (void)printw(
"Blue Moon 2.1 - by Tim Lister & Eric Raymond - Deal %d.\n",
deal);
for(row=HEARTS;row<=CLUBS;row++)
}
move(PROMPTROW + 2, 0); refresh();
-#define P(x) (void)printf("%s\n", x)
+#define P(x) (void)printw("%s\n", x)
P(" This 52-card solitaire starts with the entire deck shuffled and dealt");
P("out in four rows. The aces are then moved to the left end of the layout,");
P("making 4 initial free spaces. You may move to a space only the card that");
{
if (select[i] != NOCARD)
{
- move( BASEROW + (select[i] / GRID_WIDTH)*2+3,
- (select[i] % GRID_WIDTH)*5);
- (void)printf(" %c ", *lp++ = 'a' + i);
+ move(BASEROW + (select[i] / GRID_WIDTH)*2+3,
+ (select[i] % GRID_WIDTH)*5 - 1);
+ (void)printw(" %c ", *lp++ = 'a' + i);
}
};
*lp = '\0';
if (strlen(live) == 1)
{
move(PROMPTROW,0);
- (void)printf(
+ (void)printw(
"Making forced moves... ");
(void) fflush(stdout);
(void) sleep(1);
do {
move(PROMPTROW,0);
- (void) fputs(buf, stdout);
+ (void) addstr(buf);
move(PROMPTROW, strlen(buf));
clrtoeol();
- (void) putchar(' ');
+ (void) addch(' ');
} while
- (((c = getchar())<'a' || c>'d') && (c!='r') && (c!='q'));
+ (((c = getch())<'a' || c>'d') && (c!='r') && (c!='q'));
}
for (j = 0; j < 4; j++)
{
move(BASEROW + (select[j] / GRID_WIDTH)*2+3,
(select[j] % GRID_WIDTH)*5);
- (void)printf(" ");
+ (void)printw(" ");
}
if (c == 'r')
{
i = c-'a';
if (select[i] == NOCARD)
- (void) putchar('\007');
+ beep();
else
{
movecard(select[i], freeptr[i]);
move(PROMPTROW, 0);
standout();
- (void)printf("Finished deal %d - type any character to continue...", deal_number);
+ (void)printw("Finished deal %d - type any character to continue...", deal_number);
standend();
- (void) getchar();
+ (void) getch();
}
static int collect_discards()
int deal;
{
clear();
- (void)printf("You finished the game in %d deals. This is ",deal);
+ (void)printw("You finished the game in %d deals. This is ",deal);
standout();
if (deal<2)
- (void)printf("excellent");
+ (void)addstr("excellent");
else if (deal<4)
- (void)printf("good");
+ (void)addstr("good");
else if (deal<8)
- (void)printf("average");
+ (void)addstr("average");
else
- (void)printf("poor");
+ (void)addstr("poor");
standend();
- (void) printf(". \n");
- die(0);
+ (void) addstr(". ");
+ refresh();
}
main()
{
-#ifdef BROKEN
- (void) ioctl(0, TCGETA, &savetty);
-#endif /* BROKEN */
-
- signal(SIGINT, die);
+ (void) signal(SIGINT, die);
initscr();
-#ifdef BSD
- crmode();
-#else
+ start_color();
+ init_pair(COLOR_RED, COLOR_RED, COLOR_WHITE);
+ init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_WHITE);
+
+#if defined(__i386__) && defined(A_PCCHARSET)
+ if (tigetstr("smpch"))
+ suits = glyphs;
+#endif /* __i386__ && A_PCCHARSET */
+
cbreak();
-#endif /* BSD */
srand((int)time((long *)0));
((deck_size=collect_discards()) != 0);
game_finished(deal_number);
+
+ die(0);
}
/* blue.c ends here */