xref: /openbsd/games/gomoku/bdisp.c (revision 5c1af24d)
1 /*	$OpenBSD: bdisp.c,v 1.13 2016/01/08 21:38:33 mestre 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 <curses.h>
35 #include <err.h>
36 #include <string.h>
37 
38 #include "gomoku.h"
39 
40 #define	SCRNH		24		/* assume 24 lines for the moment */
41 #define	SCRNW		80		/* assume 80 chars for the moment */
42 
43 static	int	lastline;
44 static	char	pcolor[] = "*O.?";
45 
46 /*
47  * Initialize screen display.
48  */
49 void
cursinit(void)50 cursinit(void)
51 {
52 	initscr();
53 	if ((LINES < SCRNH) || (COLS < SCRNW)) {
54 		endwin();
55 		errx(1,"Screen too small (need %dx%d)",SCRNW,SCRNH);
56 	}
57 #ifdef KEY_MIN
58 	keypad(stdscr, TRUE);
59 #endif /* KEY_MIN */
60 	nonl();
61 	noecho();
62 	cbreak();
63 
64 #ifdef NCURSES_MOUSE_VERSION
65 	mousemask(BUTTON1_CLICKED, (mmask_t *)NULL);
66 #endif /* NCURSES_MOUSE_VERSION*/
67 }
68 
69 /*
70  * Restore screen display.
71  */
72 void
cursfini(void)73 cursfini(void)
74 {
75 	move(BSZ4, 0);
76 	clrtoeol();
77 	refresh();
78 	echo();
79 	endwin();
80 }
81 
82 /*
83  * Initialize board display.
84  */
85 void
bdisp_init(void)86 bdisp_init(void)
87 {
88 	int i, j;
89 
90 	/* top border */
91 	for (i = 1; i < BSZ1; i++) {
92 		move(0, 2 * i + 1);
93 		addch(letters[i]);
94 	}
95 	/* left and right edges */
96 	for (j = BSZ1; --j > 0; ) {
97 		move(20 - j, 0);
98 		printw("%2d ", j);
99 		move(20 - j, 2 * BSZ1 + 1);
100 		printw("%d ", j);
101 	}
102 	/* bottom border */
103 	for (i = 1; i < BSZ1; i++) {
104 		move(20, 2 * i + 1);
105 		addch(letters[i]);
106 	}
107 	bdwho(0);
108 	move(0, 47);
109 	addstr("#  black  white");
110 	lastline = 0;
111 	bdisp();
112 }
113 
114 /*
115  * Update who is playing whom.
116  */
117 void
bdwho(int update)118 bdwho(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
bdisp(void)150 bdisp(void)
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  */
bdump(FILE * fp)178 void bdump(FILE *fp)
179 {
180 	int i, j, c;
181 	struct spotstr *sp;
182 
183 	/* top border */
184 	fprintf(fp, "   A B C D E F G H J K L M N O P Q R S T\n");
185 
186 	for (j = BSZ1; --j > 0; ) {
187 		/* left edge */
188 		fprintf(fp, "%2d ", j);
189 		for (i = 1; i < BSZ1; i++) {
190 			sp = &board[i + j * BSZ1];
191 			if (debug > 1 && sp->s_occ == EMPTY) {
192 				if (sp->s_flg & IFLAGALL)
193 					c = '+';
194 				else if (sp->s_flg & CFLAGALL)
195 					c = '-';
196 				else
197 					c = '.';
198 			} else
199 				c = pcolor[sp->s_occ];
200 			putc(c, fp);
201 			putc(' ', fp);
202 		}
203 		/* right edge */
204 		fprintf(fp, "%d\n", j);
205 	}
206 
207 	/* bottom border */
208 	fprintf(fp, "   A B C D E F G H J K L M N O P Q R S T\n");
209 }
210 #endif /* DEBUG */
211 
212 /*
213  * Display a transcript entry
214  */
215 void
dislog(char * str)216 dislog(char *str)
217 {
218 
219 	if (++lastline >= SCRNH - 1) {
220 		/* move 'em up */
221 		lastline = 1;
222 	}
223 	if (strlen(str) >= SCRNW - (2 * BSZ4))
224 		str[SCRNW - (2 * BSZ4) - 1] = '\0';
225 	move(lastline, (2 * BSZ4));
226 	addstr(str);
227 	clrtoeol();
228 	move(lastline + 1, (2 * BSZ4));
229 	clrtoeol();
230 }
231 
232 /*
233  * Display a question.
234  */
235 void
ask(char * str)236 ask(char *str)
237 {
238 	int len = strlen(str);
239 
240 	move(BSZ4, 0);
241 	addstr(str);
242 	clrtoeol();
243 	move(BSZ4, len);
244 	refresh();
245 }
246 
247 int
get_line(char * buf,int size)248 get_line(char *buf, int size)
249 {
250 	char *cp, *end;
251 	int c = EOF;
252 	extern int interactive;
253 
254 	cp = buf;
255 	end = buf + size - 1;	/* save room for the '\0' */
256 	while (cp < end && (c = getchar()) != EOF && c != '\n' && c != '\r') {
257 		*cp++ = c;
258 		if (interactive) {
259 			switch (c) {
260 			case 0x0c: /* ^L */
261 				wrefresh(curscr);
262 				cp--;
263 				continue;
264 			case 0x15: /* ^U */
265 			case 0x18: /* ^X */
266 				while (cp > buf) {
267 					cp--;
268 					addch('\b');
269 				}
270 				clrtoeol();
271 				break;
272 			case '\b':
273 			case 0x7f: /* DEL */
274 				if (cp == buf + 1) {
275 					cp--;
276 					continue;
277 				}
278 				cp -= 2;
279 				addch('\b');
280 				c = ' ';
281 				/* FALLTHROUGH */
282 			default:
283 				addch(c);
284 			}
285 			refresh();
286 		}
287 	}
288 	*cp = '\0';
289 	return(c != EOF);
290 }
291 
292 
293 /* Decent (n)curses interface for the game, based on Eric S. Raymond's
294  * modifications to the battleship (bs) user interface.
295  */
getcoord(void)296 int getcoord(void)
297 {
298 	static int curx = BSZ / 2;
299 	static int cury = BSZ / 2;
300 	int ny, nx, c;
301 
302 	BGOTO(cury,curx);
303 	refresh();
304 	nx = curx; ny = cury;
305 	for (;;) {
306 		mvprintw(BSZ3, (BSZ -6)/2, "(%c %d)",
307 				'A'+ ((curx > 7) ? (curx+1) : curx), cury + 1);
308 		BGOTO(cury, curx);
309 
310 		switch(c = getch()) {
311 		case 'k': case '8':
312 #ifdef KEY_MIN
313 		case KEY_UP:
314 #endif /* KEY_MIN */
315 			ny = cury + 1;       nx = curx;
316 			break;
317 		case 'j': case '2':
318 #ifdef KEY_MIN
319 		case KEY_DOWN:
320 #endif /* KEY_MIN */
321 			ny = BSZ + cury - 1; nx = curx;
322 			break;
323 		case 'h': case '4':
324 #ifdef KEY_MIN
325 		case KEY_LEFT:
326 #endif /* KEY_MIN */
327 			ny = cury;          nx = BSZ + curx - 1;
328 			break;
329 		case 'l': case '6':
330 #ifdef KEY_MIN
331 		case KEY_RIGHT:
332 #endif /* KEY_MIN */
333 			ny = cury;          nx = curx + 1;
334 			break;
335 		case 'y': case '7':
336 #ifdef KEY_MIN
337 		case KEY_A1:
338 #endif /* KEY_MIN */
339 			ny = cury + 1;        nx = BSZ + curx - 1;
340 			break;
341 		case 'b': case '1':
342 #ifdef KEY_MIN
343 		case KEY_C1:
344 #endif /* KEY_MIN */
345 			ny = BSZ + cury - 1; nx = BSZ + curx - 1;
346 			break;
347 		case 'u': case '9':
348 #ifdef KEY_MIN
349 		case KEY_A3:
350 #endif /* KEY_MIN */
351 			ny = cury + 1;        nx = curx + 1;
352 			break;
353 		case 'n': case '3':
354 #ifdef KEY_MIN
355 		case KEY_C3:
356 #endif /* KEY_MIN */
357 			ny = BSZ + cury - 1; nx = curx + 1;
358 			break;
359 		case 'K':
360 			ny = cury + 5;       nx = curx;
361 			break;
362 		case 'J':
363 			ny = BSZ + cury - 5; nx = curx;
364 			break;
365 		case 'H':
366 			ny = cury;          nx = BSZ + curx - 5;
367 			break;
368 		case 'L':
369 			ny = cury;          nx = curx + 5;
370 			break;
371 		case 'Y':
372 			ny = cury + 5;        nx = BSZ + curx - 5;
373 			break;
374 		case 'B':
375 			ny = BSZ + cury - 5; nx = BSZ + curx - 5;
376 			break;
377 		case 'U':
378 			ny = cury + 5;        nx = curx + 5;
379 			break;
380 		case 'N':
381 			ny = BSZ + cury - 5; nx = curx + 5;
382 			break;
383 		case FF:
384 			nx = curx; ny = cury;
385 			(void)clearok(stdscr, TRUE);
386 			(void)refresh();
387 			break;
388 #ifdef NCURSES_MOUSE_VERSION
389 		case KEY_MOUSE:
390 		{
391 			MEVENT	myevent;
392 
393 			getmouse(&myevent);
394 			if (myevent.y >= 1 && myevent.y <= BSZ1
395 				&& myevent.x >= 3 && myevent.x <= (2 * BSZ + 1))
396 			{
397 				curx = (myevent.x - 3) / 2;
398 				cury = BSZ - myevent.y;
399 				return(PT(curx,cury));
400 			}
401 			else
402 				beep();
403 		}
404 		break;
405 #endif /* NCURSES_MOUSE_VERSION */
406 		case 'Q':
407 			return(RESIGN);
408 			break;
409 		case 'S':
410 			return(SAVE);
411 			break;
412 		case ' ':
413 		case '\015':  /* return */
414 			(void) mvaddstr(BSZ3, (BSZ -6)/2, "      ");
415 			return(PT(curx+1,cury+1));
416 			break;
417 	}
418 
419 	curx = nx % BSZ;
420 	cury = ny % BSZ;
421     }
422 }
423