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