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