Better user interface. From OpenBSD, written by Paul Janzen quite a
long time ago. A few minor adjustments by yours truly.
This commit is contained in:
parent
6c6b8bd86e
commit
4a11aa7558
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: bdisp.c,v 1.13 2010/03/29 02:21:04 dholland Exp $ */
|
||||
/* $NetBSD: bdisp.c,v 1.14 2010/03/29 03:51:55 dholland Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
|
@ -37,7 +37,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)bdisp.c 8.2 (Berkeley) 5/3/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: bdisp.c,v 1.13 2010/03/29 02:21:04 dholland Exp $");
|
||||
__RCSID("$NetBSD: bdisp.c,v 1.14 2010/03/29 03:51:55 dholland Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -66,9 +66,19 @@ cursinit(void)
|
|||
if (!initscr()) {
|
||||
errx(EXIT_FAILURE, "Couldn't initialize screen");
|
||||
}
|
||||
if ((LINES < SCRNH) || (COLS < SCRNW)) {
|
||||
errx(EXIT_FAILURE, "Screen too small (need %d%xd)",
|
||||
SCRNW, SCRNH);
|
||||
}
|
||||
keypad(stdscr, TRUE);
|
||||
nonl();
|
||||
noecho();
|
||||
cbreak();
|
||||
leaveok(stdscr, TRUE);
|
||||
leaveok(stdscr, FALSE);
|
||||
|
||||
#if 0 /* no mouse support in netbsd curses yet */
|
||||
mousemask(BUTTON1_CLICKED, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -78,10 +88,10 @@ void
|
|||
cursfini(void)
|
||||
{
|
||||
|
||||
leaveok(stdscr, FALSE);
|
||||
move(23, 0);
|
||||
move(BSZ4, 0);
|
||||
clrtoeol();
|
||||
refresh();
|
||||
echo();
|
||||
endwin();
|
||||
}
|
||||
|
||||
|
@ -123,18 +133,28 @@ bdisp_init(void)
|
|||
void
|
||||
bdwho(int update)
|
||||
{
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
move(21, 0);
|
||||
clrtoeol();
|
||||
i = 6 - strlen(plyr[BLACK]) / 2;
|
||||
move(21, i > 0 ? i : 0);
|
||||
printw("BLACK/%s", plyr[BLACK]);
|
||||
i = 30 - strlen(plyr[WHITE]) / 2;
|
||||
move(21, i);
|
||||
printw("WHITE/%s", plyr[WHITE]);
|
||||
move(21, 19);
|
||||
addstr(" vs. ");
|
||||
printw(" ");
|
||||
i = strlen(plyr[BLACK]);
|
||||
j = strlen(plyr[WHITE]);
|
||||
if (i + j <= 20) {
|
||||
move(21, 10 - (i+j)/2);
|
||||
printw("BLACK/%s (*) vs. WHITE/%s (O)",
|
||||
plyr[BLACK], plyr[WHITE]);
|
||||
} else {
|
||||
move(21, 0);
|
||||
if (i <= 10) {
|
||||
j = 20 - i;
|
||||
} else if (j <= 10) {
|
||||
i = 20 - j;
|
||||
} else {
|
||||
i = j = 10;
|
||||
}
|
||||
printw("BLACK/%.*s (*) vs. WHITE/%.*s (O)",
|
||||
i, plyr[BLACK], j, plyr[WHITE]);
|
||||
}
|
||||
if (update)
|
||||
refresh();
|
||||
}
|
||||
|
@ -217,10 +237,10 @@ dislog(const char *str)
|
|||
/* move 'em up */
|
||||
lastline = 1;
|
||||
}
|
||||
move(lastline, 46);
|
||||
addnstr(str, SCRNW - 46 - 1);
|
||||
move(lastline, TRANSCRIPT_COL);
|
||||
addnstr(str, SCRNW - TRANSCRIPT_COL - 1);
|
||||
clrtoeol();
|
||||
move(lastline + 1, 46);
|
||||
move(lastline + 1, TRANSCRIPT_COL);
|
||||
clrtoeol();
|
||||
}
|
||||
|
||||
|
@ -233,10 +253,10 @@ ask(const char *str)
|
|||
{
|
||||
int len = strlen(str);
|
||||
|
||||
move(23, 0);
|
||||
move(BSZ4, 0);
|
||||
addstr(str);
|
||||
clrtoeol();
|
||||
move(23, len);
|
||||
move(BSZ4, len);
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
@ -284,3 +304,146 @@ get_line(char *buf, int size)
|
|||
*cp = '\0';
|
||||
return(c != EOF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decent (n)curses interface for the game, based on Eric S. Raymond's
|
||||
* modifications to the battleship (bs) user interface.
|
||||
*/
|
||||
int
|
||||
get_coord(void)
|
||||
{
|
||||
static int curx = BSZ / 2;
|
||||
static int cury = BSZ / 2;
|
||||
int ny, nx, ch;
|
||||
|
||||
BGOTO(cury, curx);
|
||||
refresh();
|
||||
nx = curx;
|
||||
ny = cury;
|
||||
for (;;) {
|
||||
mvprintw(BSZ3, (BSZ -6)/2, "(%c %d)",
|
||||
'A'+ ((curx > 7) ? (curx+1) : curx), cury + 1);
|
||||
BGOTO(cury, curx);
|
||||
|
||||
ch = getch();
|
||||
switch (ch) {
|
||||
case 'k':
|
||||
case '8':
|
||||
case KEY_UP:
|
||||
nx = curx;
|
||||
ny = cury + 1;
|
||||
break;
|
||||
case 'j':
|
||||
case '2':
|
||||
case KEY_DOWN:
|
||||
nx = curx;
|
||||
ny = BSZ + cury - 1;
|
||||
break;
|
||||
case 'h':
|
||||
case '4':
|
||||
case KEY_LEFT:
|
||||
nx = BSZ + curx - 1;
|
||||
ny = cury;
|
||||
break;
|
||||
case 'l':
|
||||
case '6':
|
||||
case KEY_RIGHT:
|
||||
nx = curx + 1;
|
||||
ny = cury;
|
||||
break;
|
||||
case 'y':
|
||||
case '7':
|
||||
case KEY_A1:
|
||||
nx = BSZ + curx - 1;
|
||||
ny = cury + 1;
|
||||
break;
|
||||
case 'b':
|
||||
case '1':
|
||||
case KEY_C1:
|
||||
nx = BSZ + curx - 1;
|
||||
ny = BSZ + cury - 1;
|
||||
break;
|
||||
case 'u':
|
||||
case '9':
|
||||
case KEY_A3:
|
||||
nx = curx + 1;
|
||||
ny = cury + 1;
|
||||
break;
|
||||
case 'n':
|
||||
case '3':
|
||||
case KEY_C3:
|
||||
nx = curx + 1;
|
||||
ny = BSZ + cury - 1;
|
||||
break;
|
||||
case 'K':
|
||||
nx = curx;
|
||||
ny = cury + 5;
|
||||
break;
|
||||
case 'J':
|
||||
nx = curx;
|
||||
ny = BSZ + cury - 5;
|
||||
break;
|
||||
case 'H':
|
||||
nx = BSZ + curx - 5;
|
||||
ny = cury;
|
||||
break;
|
||||
case 'L':
|
||||
nx = curx + 5;
|
||||
ny = cury;
|
||||
break;
|
||||
case 'Y':
|
||||
nx = BSZ + curx - 5;
|
||||
ny = cury + 5;
|
||||
break;
|
||||
case 'B':
|
||||
nx = BSZ + curx - 5;
|
||||
ny = BSZ + cury - 5;
|
||||
break;
|
||||
case 'U':
|
||||
nx = curx + 5;
|
||||
ny = cury + 5;
|
||||
break;
|
||||
case 'N':
|
||||
nx = curx + 5;
|
||||
ny = BSZ + cury - 5;
|
||||
break;
|
||||
case '\f':
|
||||
nx = curx;
|
||||
ny = cury;
|
||||
(void)clearok(stdscr, TRUE);
|
||||
(void)refresh();
|
||||
break;
|
||||
#if 0 /* notyet */
|
||||
case KEY_MOUSE:
|
||||
{
|
||||
MEVENT myevent;
|
||||
|
||||
getmouse(&myevent);
|
||||
if (myevent.y >= 1 && myevent.y <= BSZ1 &&
|
||||
myevent.x >= 3 && myevent.x <= (2 * BSZ + 1)) {
|
||||
curx = (myevent.x - 3) / 2;
|
||||
cury = BSZ - myevent.y;
|
||||
return PT(curx,cury);
|
||||
} else {
|
||||
beep();
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* 0 */
|
||||
case 'Q':
|
||||
return RESIGN;
|
||||
break;
|
||||
case 'S':
|
||||
return SAVE;
|
||||
break;
|
||||
case ' ':
|
||||
case '\r':
|
||||
(void) mvaddstr(BSZ3, (BSZ -6)/2, " ");
|
||||
return PT(curx+1,cury+1);
|
||||
break;
|
||||
}
|
||||
|
||||
curx = nx % BSZ;
|
||||
cury = ny % BSZ;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: gomoku.6,v 1.13 2010/03/29 02:34:50 dholland Exp $
|
||||
.\" $NetBSD: gomoku.6,v 1.14 2010/03/29 03:51:55 dholland Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1994
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
|
@ -32,7 +32,7 @@
|
|||
.\"
|
||||
.\" @(#)gomoku.6 8.2 (Berkeley) 8/4/94
|
||||
.\"
|
||||
.Dd August 4, 1994
|
||||
.Dd March 28, 2010
|
||||
.Dt GOMOKU 6
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -42,7 +42,7 @@
|
|||
.Nm
|
||||
.Op Fl bcdu
|
||||
.Op Fl D Ar debugfile
|
||||
.Op Ar inputfile
|
||||
.Op Ar savefile
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a two player game where the object is to get 5 in a row horizontally,
|
||||
|
@ -51,19 +51,26 @@ By convention, black always moves first.
|
|||
With no arguments,
|
||||
.Nm
|
||||
will display a playing board and prompt for moves from the user.
|
||||
Valid moves are a letter for the column and a number for the row of an empty
|
||||
board location.
|
||||
Entering
|
||||
.Dq quit
|
||||
or
|
||||
.Dq resign
|
||||
will end the game.
|
||||
You can save the current state of the game by entering
|
||||
.Dq save
|
||||
and supplying a file name when prompted.
|
||||
The optional file
|
||||
.Ar inputfile
|
||||
can be used to restore a saved game.
|
||||
Moves may be entered by selecting the desired board location and
|
||||
pressing the space or enter key.
|
||||
The cursor may be moved using the arrow keys or
|
||||
.Xr vi 1
|
||||
motion keys
|
||||
.Em hjklyubn .
|
||||
These also may be familiar from
|
||||
.Xr rogue 6
|
||||
and
|
||||
.Xr hack 6 .
|
||||
.\" Valid moves are a letter for the column and a number for the row
|
||||
.\" of an empty board location.
|
||||
To quit, type
|
||||
.Sq Q ,
|
||||
and to save the game, type
|
||||
.Sq S
|
||||
and supply a file name when prompted.
|
||||
To restore a saved game, pass the file name on the
|
||||
.Nm
|
||||
command line.
|
||||
.Pp
|
||||
The options are:
|
||||
.Bl -tag -width Ds
|
||||
|
@ -102,3 +109,7 @@ This is mostly used for testing.
|
|||
The board display routines were based on the
|
||||
.Nm goref
|
||||
program written by Peter Langston.
|
||||
The user interface was based on Eric S. Raymond's interface for
|
||||
.\" change this when/if we import openbsd's bs(6)
|
||||
.\" .Xr bs 6 .
|
||||
.Nm bs .
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: gomoku.h,v 1.17 2009/08/12 06:19:17 dholland Exp $ */
|
||||
/* $NetBSD: gomoku.h,v 1.18 2010/03/29 03:51:55 dholland Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
|
@ -42,9 +42,16 @@
|
|||
#define BSZ 19
|
||||
#define BSZ1 (BSZ+1)
|
||||
#define BSZ2 (BSZ+2)
|
||||
#define BSZ3 (BSZ+3)
|
||||
#define BSZ4 (BSZ+4)
|
||||
#define BAREA (BSZ2*BSZ1+1)
|
||||
|
||||
/* frame dimentions (based on 5 in a row) */
|
||||
#define TRANSCRIPT_COL 46 /* necessarily == 2*BSZ4 */
|
||||
|
||||
/* interactive curses stuff */
|
||||
#define BGOTO(y,x) move(BSZ - (y), 2 * (x) + 3)
|
||||
|
||||
/* frame dimensions (based on 5 in a row) */
|
||||
#define FSZ1 BSZ
|
||||
#define FSZ2 (BSZ-4)
|
||||
#define FAREA (FSZ1*FSZ2 + FSZ2*FSZ2 + FSZ1*FSZ2 + FSZ2*FSZ2)
|
||||
|
@ -261,6 +268,7 @@ extern int debug;
|
|||
#define ASSERT(x)
|
||||
|
||||
void bdinit(struct spotstr *);
|
||||
int get_coord(void);
|
||||
int get_line(char *, int);
|
||||
void ask(const char *);
|
||||
void dislog(const char *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: main.c,v 1.22 2010/03/29 02:48:17 dholland Exp $ */
|
||||
/* $NetBSD: main.c,v 1.23 2010/03/29 03:51:55 dholland Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
|
@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1994\
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: main.c,v 1.22 2010/03/29 02:48:17 dholland Exp $");
|
||||
__RCSID("$NetBSD: main.c,v 1.23 2010/03/29 03:51:55 dholland Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -66,6 +66,7 @@ int interactive = 1; /* true if interactive */
|
|||
int debug; /* true if debugging */
|
||||
static int test; /* both moves come from 1: input, 2: computer */
|
||||
static char *prog; /* name of program */
|
||||
static char user[LOGIN_NAME_MAX]; /* name of player */
|
||||
static FILE *debugfp; /* file for debug output */
|
||||
static FILE *inputfp; /* file for debug input */
|
||||
|
||||
|
@ -90,6 +91,7 @@ main(int argc, char **argv)
|
|||
{
|
||||
char buf[128];
|
||||
char fname[PATH_MAX];
|
||||
char *tmp;
|
||||
int color, curmove, i, ch;
|
||||
int input[2];
|
||||
static const char *const fmt[2] = {
|
||||
|
@ -100,6 +102,13 @@ main(int argc, char **argv)
|
|||
/* Revoke setgid privileges */
|
||||
setgid(getgid());
|
||||
|
||||
tmp = getlogin();
|
||||
if (tmp) {
|
||||
strlcpy(user, tmp, sizeof(user));
|
||||
} else {
|
||||
strcpy(user, "you");
|
||||
}
|
||||
|
||||
color = curmove = 0;
|
||||
|
||||
prog = strrchr(argv[0], '/');
|
||||
|
@ -156,21 +165,21 @@ again:
|
|||
#endif
|
||||
|
||||
if (inputfp == NULL && test == 0) {
|
||||
ask("black or white? ");
|
||||
for (;;) {
|
||||
ask("black or white? ");
|
||||
get_line(buf, sizeof(buf));
|
||||
if (buf[0] == 'b' || buf[0] == 'B') {
|
||||
ch = getchar();
|
||||
if (ch == 'b' || ch == 'B') {
|
||||
color = BLACK;
|
||||
break;
|
||||
}
|
||||
if (buf[0] == 'w' || buf[0] == 'W') {
|
||||
if (ch == 'w' || ch == 'W') {
|
||||
color = WHITE;
|
||||
break;
|
||||
}
|
||||
move(22, 0);
|
||||
move(BSZ3, 0);
|
||||
printw("Black moves first. Please enter `black' or `white'\n");
|
||||
}
|
||||
move(22, 0);
|
||||
move(BSZ3, 0);
|
||||
clrtoeol();
|
||||
}
|
||||
} else {
|
||||
|
@ -208,8 +217,8 @@ again:
|
|||
}
|
||||
}
|
||||
if (interactive) {
|
||||
plyr[BLACK] = input[BLACK] == USER ? "you" : prog;
|
||||
plyr[WHITE] = input[WHITE] == USER ? "you" : prog;
|
||||
plyr[BLACK] = input[BLACK] == USER ? user : prog;
|
||||
plyr[WHITE] = input[WHITE] == USER ? user : prog;
|
||||
bdwho(1);
|
||||
}
|
||||
|
||||
|
@ -236,23 +245,16 @@ again:
|
|||
input[WHITE] = PROGRAM;
|
||||
break;
|
||||
}
|
||||
plyr[BLACK] = input[BLACK] == USER ? "you" : prog;
|
||||
plyr[WHITE] = input[WHITE] == USER ? "you" : prog;
|
||||
plyr[BLACK] = input[BLACK] == USER ? user : prog;
|
||||
plyr[WHITE] = input[WHITE] == USER ? user : prog;
|
||||
bdwho(1);
|
||||
goto top;
|
||||
|
||||
case USER: /* input comes from standard input */
|
||||
getinput:
|
||||
if (interactive)
|
||||
ask("move? ");
|
||||
if (!get_line(buf, sizeof(buf))) {
|
||||
curmove = RESIGN;
|
||||
break;
|
||||
}
|
||||
if (buf[0] == '\0')
|
||||
goto getinput;
|
||||
curmove = ctos(buf);
|
||||
if (interactive) {
|
||||
ask("move? ");
|
||||
curmove = get_coord();
|
||||
if (curmove == SAVE) {
|
||||
FILE *fp;
|
||||
|
||||
|
@ -270,13 +272,24 @@ again:
|
|||
}
|
||||
if (curmove != RESIGN &&
|
||||
board[curmove].s_occ != EMPTY) {
|
||||
misclog("Illegal move");
|
||||
/*misclog("Illegal move");*/
|
||||
beep();
|
||||
goto getinput;
|
||||
}
|
||||
} else {
|
||||
if (!get_line(buf, sizeof(buf))) {
|
||||
curmove = RESIGN;
|
||||
break;
|
||||
}
|
||||
if (buf[0] == '\0')
|
||||
goto getinput;
|
||||
curmove = ctos(buf);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROGRAM: /* input comes from the program */
|
||||
if (interactive)
|
||||
ask("Thinking...");
|
||||
curmove = pickmove(color);
|
||||
break;
|
||||
}
|
||||
|
@ -289,11 +302,13 @@ again:
|
|||
bdisp();
|
||||
}
|
||||
if (interactive) {
|
||||
move(22, 0);
|
||||
move(BSZ3, 0);
|
||||
switch (i) {
|
||||
case WIN:
|
||||
if (input[color] == PROGRAM)
|
||||
addstr("Ha ha, I won");
|
||||
else if (input[0] == USER && input[1] == USER)
|
||||
addstr("Well, you won (and lost)");
|
||||
else
|
||||
addstr("Rats! you won");
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue