summaryrefslogtreecommitdiffstats
path: root/gomoku
diff options
context:
space:
mode:
authordholland <dholland@NetBSD.org>2010-03-29 03:51:55 +0000
committerdholland <dholland@NetBSD.org>2010-03-29 03:51:55 +0000
commit3c3f8c0880fed372a83ed917c866247edb974156 (patch)
tree3f30a09a6be5d23ab795fef993a908ad3695c16d /gomoku
parente92892fbd077218b61c0a3325de6df66494b4589 (diff)
downloadbsdgames-darwin-3c3f8c0880fed372a83ed917c866247edb974156.tar.gz
bsdgames-darwin-3c3f8c0880fed372a83ed917c866247edb974156.tar.zst
bsdgames-darwin-3c3f8c0880fed372a83ed917c866247edb974156.zip
Better user interface. From OpenBSD, written by Paul Janzen quite a
long time ago. A few minor adjustments by yours truly.
Diffstat (limited to 'gomoku')
-rw-r--r--gomoku/bdisp.c203
-rw-r--r--gomoku/gomoku.643
-rw-r--r--gomoku/gomoku.h12
-rw-r--r--gomoku/main.c61
4 files changed, 258 insertions, 61 deletions
diff --git a/gomoku/bdisp.c b/gomoku/bdisp.c
index fe227618..075ea172 100644
--- a/gomoku/bdisp.c
+++ b/gomoku/bdisp.c
@@ -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;
+ }
+}
diff --git a/gomoku/gomoku.6 b/gomoku/gomoku.6
index 6abec4b0..0a36d6d3 100644
--- a/gomoku/gomoku.6
+++ b/gomoku/gomoku.6
@@ -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 .
diff --git a/gomoku/gomoku.h b/gomoku/gomoku.h
index bf83379a..bf97b1cf 100644
--- a/gomoku/gomoku.h
+++ b/gomoku/gomoku.h
@@ -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 *);
diff --git a/gomoku/main.c b/gomoku/main.c
index f557c64b..769bfef7 100644
--- a/gomoku/main.c
+++ b/gomoku/main.c
@@ -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;