xref: /netbsd-src/games/gomoku/bdisp.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: bdisp.c,v 1.17 2014/03/22 18:58:57 dholland Exp $	*/
2 
3 /*
4  * Copyright (c) 1994
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Ralph Campbell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)bdisp.c	8.2 (Berkeley) 5/3/95";
39 #else
40 __RCSID("$NetBSD: bdisp.c,v 1.17 2014/03/22 18:58:57 dholland Exp $");
41 #endif
42 #endif /* not lint */
43 
44 #include <curses.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <err.h>
48 #include "gomoku.h"
49 
50 #define	SCRNH		24		/* assume 24 lines for the moment */
51 #define	SCRNW		80		/* assume 80 chars for the moment */
52 
53 static	int	lastline;
54 static	char	pcolor[] = "*O.?";
55 
56 /*
57  * Initialize screen display.
58  */
59 void
60 cursinit(void)
61 {
62 
63 	if (!initscr()) {
64 		errx(EXIT_FAILURE, "Couldn't initialize screen");
65 	}
66 	if ((LINES < SCRNH) || (COLS < SCRNW)) {
67 		errx(EXIT_FAILURE, "Screen too small (need %d%xd)",
68 		    SCRNW, SCRNH);
69 	}
70 	keypad(stdscr, TRUE);
71 	nonl();
72 	noecho();
73 	cbreak();
74 	leaveok(stdscr, FALSE);
75 
76 #if 0 /* no mouse support in netbsd curses yet */
77 	mousemask(BUTTON1_CLICKED, NULL);
78 #endif
79 }
80 
81 /*
82  * Restore screen display.
83  */
84 void
85 cursfini(void)
86 {
87 
88 	move(BSZ4, 0);
89 	clrtoeol();
90 	refresh();
91 	echo();
92 	endwin();
93 }
94 
95 /*
96  * Initialize board display.
97  */
98 void
99 bdisp_init(void)
100 {
101 	int i, j;
102 
103 	/* top border */
104 	for (i = 1; i < BSZ1; i++) {
105 		move(0, 2 * i + 1);
106 		addch(letters[i]);
107 	}
108 	/* left and right edges */
109 	for (j = BSZ1; --j > 0; ) {
110 		move(20 - j, 0);
111 		printw("%2d ", j);
112 		move(20 - j, 2 * BSZ1 + 1);
113 		printw("%d ", j);
114 	}
115 	/* bottom border */
116 	for (i = 1; i < BSZ1; i++) {
117 		move(20, 2 * i + 1);
118 		addch(letters[i]);
119 	}
120 	bdwho(0);
121 	move(0, 47);
122 	addstr("#  black  white");
123 	lastline = 0;
124 	bdisp();
125 }
126 
127 /*
128  * Update who is playing whom.
129  */
130 void
131 bdwho(int update)
132 {
133 	int i, j;
134 
135 	move(21, 0);
136         printw("                                              ");
137 	i = strlen(plyr[BLACK]);
138 	j = strlen(plyr[WHITE]);
139 	if (i + j <= 20) {
140 		move(21, 10 - (i+j)/2);
141 		printw("BLACK/%s (*) vs. WHITE/%s (O)",
142 		    plyr[BLACK], plyr[WHITE]);
143 	} else {
144 		move(21, 0);
145 		if (i <= 10) {
146 			j = 20 - i;
147 		} else if (j <= 10) {
148 			i = 20 - j;
149 		} else {
150 			i = j = 10;
151 		}
152 		printw("BLACK/%.*s (*) vs. WHITE/%.*s (O)",
153 		    i, plyr[BLACK], j, plyr[WHITE]);
154 	}
155 	if (update)
156 		refresh();
157 }
158 
159 /*
160  * Update the board display after a move.
161  */
162 void
163 bdisp(void)
164 {
165 	int i, j, c;
166 	struct spotstr *sp;
167 
168 	for (j = BSZ1; --j > 0; ) {
169 		for (i = 1; i < BSZ1; i++) {
170 			move(BSZ1 - j, 2 * i + 1);
171 			sp = &board[i + j * BSZ1];
172 			if (debug > 1 && sp->s_occ == EMPTY) {
173 				if (sp->s_flags & IFLAGALL)
174 					c = '+';
175 				else if (sp->s_flags & CFLAGALL)
176 					c = '-';
177 				else
178 					c = '.';
179 			} else
180 				c = pcolor[sp->s_occ];
181 			addch(c);
182 		}
183 	}
184 	refresh();
185 }
186 
187 #ifdef DEBUG
188 /*
189  * Dump board display to a file.
190  */
191 void
192 bdump(FILE *fp)
193 {
194 	int i, j, c;
195 	struct spotstr *sp;
196 
197 	/* top border */
198 	fprintf(fp, "   A B C D E F G H J K L M N O P Q R S T\n");
199 
200 	for (j = BSZ1; --j > 0; ) {
201 		/* left edge */
202 		fprintf(fp, "%2d ", j);
203 		for (i = 1; i < BSZ1; i++) {
204 			sp = &board[i + j * BSZ1];
205 			if (debug > 1 && sp->s_occ == EMPTY) {
206 				if (sp->s_flags & IFLAGALL)
207 					c = '+';
208 				else if (sp->s_flags & CFLAGALL)
209 					c = '-';
210 				else
211 					c = '.';
212 			} else
213 				c = pcolor[sp->s_occ];
214 			putc(c, fp);
215 			putc(' ', fp);
216 		}
217 		/* right edge */
218 		fprintf(fp, "%d\n", j);
219 	}
220 
221 	/* bottom border */
222 	fprintf(fp, "   A B C D E F G H J K L M N O P Q R S T\n");
223 }
224 #endif /* DEBUG */
225 
226 /*
227  * Display a transcript entry
228  */
229 void
230 dislog(const char *str)
231 {
232 
233 	if (++lastline >= SCRNH - 1) {
234 		/* move 'em up */
235 		lastline = 1;
236 	}
237 	move(lastline, TRANSCRIPT_COL);
238 	addnstr(str, SCRNW - TRANSCRIPT_COL - 1);
239 	clrtoeol();
240 	move(lastline + 1, TRANSCRIPT_COL);
241 	clrtoeol();
242 }
243 
244 /*
245  * Display a question.
246  */
247 
248 void
249 ask(const char *str)
250 {
251 	int len = strlen(str);
252 
253 	move(BSZ4, 0);
254 	addstr(str);
255 	clrtoeol();
256 	move(BSZ4, len);
257 	refresh();
258 }
259 
260 int
261 get_key(const char *allowed)
262 {
263 	int ch;
264 
265 	while (1) {
266 		ch = getch();
267 		if (allowed != NULL &&
268 		    ch != '\0' && strchr(allowed, ch) == NULL) {
269 			beep();
270 			refresh();
271 			continue;
272 		}
273 		break;
274 	}
275 	return ch;
276 }
277 
278 int
279 get_line(char *buf, int size)
280 {
281 	char *cp, *end;
282 	int c;
283 
284 	c = 0;
285 	cp = buf;
286 	end = buf + size - 1;	/* save room for the '\0' */
287 	while (cp < end && (c = getchar()) != EOF && c != '\n' && c != '\r') {
288 		*cp++ = c;
289 		if (interactive) {
290 			switch (c) {
291 			case 0x0c: /* ^L */
292 				wrefresh(curscr);
293 				cp--;
294 				continue;
295 			case 0x15: /* ^U */
296 			case 0x18: /* ^X */
297 				while (cp > buf) {
298 					cp--;
299 					addch('\b');
300 				}
301 				clrtoeol();
302 				break;
303 			case '\b':
304 			case 0x7f: /* DEL */
305 				if (cp == buf + 1) {
306 					cp--;
307 					continue;
308 				}
309 				cp -= 2;
310 				addch('\b');
311 				c = ' ';
312 				/* FALLTHROUGH */
313 			default:
314 				addch(c);
315 			}
316 			refresh();
317 		}
318 	}
319 	*cp = '\0';
320 	return(c != EOF);
321 }
322 
323 /*
324  * Decent (n)curses interface for the game, based on Eric S. Raymond's
325  * modifications to the battleship (bs) user interface.
326  */
327 int
328 get_coord(void)
329 {
330 	static int curx = BSZ / 2;
331 	static int cury = BSZ / 2;
332 	int ny, nx, ch;
333 
334 	BGOTO(cury, curx);
335 	refresh();
336 	nx = curx;
337 	ny = cury;
338 	for (;;) {
339 		mvprintw(BSZ3, (BSZ -6)/2, "(%c %d) ",
340 				'A'+ ((curx > 7) ? (curx+1) : curx), cury + 1);
341 		BGOTO(cury, curx);
342 
343 		ch = getch();
344 		switch (ch) {
345 		case 'k':
346 		case '8':
347 		case KEY_UP:
348 			nx = curx;
349 			ny = cury + 1;
350 			break;
351 		case 'j':
352 		case '2':
353 		case KEY_DOWN:
354 			nx = curx;
355 			ny = BSZ + cury - 1;
356 			break;
357 		case 'h':
358 		case '4':
359 		case KEY_LEFT:
360 			nx = BSZ + curx - 1;
361 			ny = cury;
362 			break;
363 		case 'l':
364 		case '6':
365 		case KEY_RIGHT:
366 			nx = curx + 1;
367 			ny = cury;
368 			break;
369 		case 'y':
370 		case '7':
371 		case KEY_A1:
372 			nx = BSZ + curx - 1;
373 			ny = cury + 1;
374 			break;
375 		case 'b':
376 		case '1':
377 		case KEY_C1:
378 			nx = BSZ + curx - 1;
379 			ny = BSZ + cury - 1;
380 			break;
381 		case 'u':
382 		case '9':
383 		case KEY_A3:
384 			nx = curx + 1;
385 			ny = cury + 1;
386 			break;
387 		case 'n':
388 		case '3':
389 		case KEY_C3:
390 			nx = curx + 1;
391 			ny = BSZ + cury - 1;
392 			break;
393 		case 'K':
394 			nx = curx;
395 			ny = cury + 5;
396 			break;
397 		case 'J':
398 			nx = curx;
399 			ny = BSZ + cury - 5;
400 			break;
401 		case 'H':
402 			nx = BSZ + curx - 5;
403 			ny = cury;
404 			break;
405 		case 'L':
406 			nx = curx + 5;
407 			ny = cury;
408 			break;
409 		case 'Y':
410 		        nx = BSZ + curx - 5;
411 			ny = cury + 5;
412 			break;
413 		case 'B':
414 			nx = BSZ + curx - 5;
415 			ny = BSZ + cury - 5;
416 			break;
417 		case 'U':
418 			nx = curx + 5;
419 			ny = cury + 5;
420 			break;
421 		case 'N':
422 			nx = curx + 5;
423 			ny = BSZ + cury - 5;
424 			break;
425 		case '\f':
426 			nx = curx;
427 			ny = cury;
428 			(void)clearok(stdscr, TRUE);
429 			(void)refresh();
430 			break;
431 #if 0 /* notyet */
432 		case KEY_MOUSE:
433 		{
434 			MEVENT	myevent;
435 
436 			getmouse(&myevent);
437 			if (myevent.y >= 1 && myevent.y <= BSZ1 &&
438 			    myevent.x >= 3 && myevent.x <= (2 * BSZ + 1)) {
439 				curx = (myevent.x - 3) / 2;
440 				cury = BSZ - myevent.y;
441 				return PT(curx,cury);
442 			} else {
443 				beep();
444 			}
445 		}
446 		break;
447 #endif /* 0 */
448 		case 'Q':
449 		case 'q':
450 			return RESIGN;
451 			break;
452 		case 'S':
453 		case 's':
454 			return SAVE;
455 			break;
456 		case ' ':
457 		case '\r':
458 			(void) mvaddstr(BSZ3, (BSZ -6)/2, "      ");
459 			return PT(curx+1,cury+1);
460 			break;
461 	}
462 
463 	curx = nx % BSZ;
464 	cury = ny % BSZ;
465     }
466 }
467