Module Name:    src
Committed By:   dholland
Date:           Mon Mar 29 03:51:55 UTC 2010

Modified Files:
        src/games/gomoku: bdisp.c gomoku.6 gomoku.h main.c

Log Message:
Better user interface. From OpenBSD, written by Paul Janzen quite a
long time ago. A few minor adjustments by yours truly.


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/games/gomoku/bdisp.c src/games/gomoku/gomoku.6
cvs rdiff -u -r1.17 -r1.18 src/games/gomoku/gomoku.h
cvs rdiff -u -r1.22 -r1.23 src/games/gomoku/main.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/games/gomoku/bdisp.c
diff -u src/games/gomoku/bdisp.c:1.13 src/games/gomoku/bdisp.c:1.14
--- src/games/gomoku/bdisp.c:1.13	Mon Mar 29 02:21:04 2010
+++ src/games/gomoku/bdisp.c	Mon Mar 29 03:51:55 2010
@@ -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 @@
 	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 @@
 cursfini(void)
 {
 
-	leaveok(stdscr, FALSE);
-	move(23, 0);
+	move(BSZ4, 0);
 	clrtoeol();
 	refresh();
+	echo();
 	endwin();
 }
 
@@ -123,18 +133,28 @@
 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 @@
 		/* 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 @@
 {
 	int len = strlen(str);
 
-	move(23, 0);
+	move(BSZ4, 0);
 	addstr(str);
 	clrtoeol();
-	move(23, len);
+	move(BSZ4, len);
 	refresh();
 }
 
@@ -284,3 +304,146 @@
 	*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;
+    }
+}
Index: src/games/gomoku/gomoku.6
diff -u src/games/gomoku/gomoku.6:1.13 src/games/gomoku/gomoku.6:1.14
--- src/games/gomoku/gomoku.6:1.13	Mon Mar 29 02:34:50 2010
+++ src/games/gomoku/gomoku.6	Mon Mar 29 03:51:55 2010
@@ -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 @@
 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 @@
 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 .

Index: src/games/gomoku/gomoku.h
diff -u src/games/gomoku/gomoku.h:1.17 src/games/gomoku/gomoku.h:1.18
--- src/games/gomoku/gomoku.h:1.17	Wed Aug 12 06:19:17 2009
+++ src/games/gomoku/gomoku.h	Mon Mar 29 03:51:55 2010
@@ -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 @@
 #define ASSERT(x)
 
 void	bdinit(struct spotstr *);
+int	get_coord(void);
 int	get_line(char *, int);
 void	ask(const char *);
 void	dislog(const char *);

Index: src/games/gomoku/main.c
diff -u src/games/gomoku/main.c:1.22 src/games/gomoku/main.c:1.23
--- src/games/gomoku/main.c:1.22	Mon Mar 29 02:48:17 2010
+++ src/games/gomoku/main.c	Mon Mar 29 03:51:55 2010
@@ -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 @@
 #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	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 @@
 {
 	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 @@
 	/* 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 @@
 #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 @@
 		}
 	}
 	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 @@
 				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 @@
 				}
 				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 @@
 			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;

Reply via email to