xref: /netbsd/games/sail/pl_7.c (revision bf9ec67e)
1 /*	$NetBSD: pl_7.c,v 1.26 2001/12/06 12:21:00 blymn Exp $	*/
2 
3 /*
4  * Copyright (c) 1983, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)pl_7.c	8.1 (Berkeley) 5/31/93";
40 #else
41 __RCSID("$NetBSD: pl_7.c,v 1.26 2001/12/06 12:21:00 blymn Exp $");
42 #endif
43 #endif /* not lint */
44 
45 #include <curses.h>
46 #include <signal.h>
47 #include <stdarg.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <string.h>
52 #include "extern.h"
53 #include "player.h"
54 #include "display.h"
55 
56 static void	Scroll(void);
57 static void	endprompt(int);
58 static void	adjustview(void);
59 
60 /*
61  * Display interface
62  */
63 
64 static char sc_hasprompt;
65 static const char *sc_prompt;
66 static const char *sc_buf;
67 static int sc_line;
68 
69 WINDOW *view_w;
70 WINDOW *slot_w;
71 WINDOW *scroll_w;
72 WINDOW *stat_w;
73 WINDOW *turn_w;
74 
75 int done_curses;
76 int loaded, fired, changed, repaired;
77 int dont_adjust;
78 int viewrow, viewcol;
79 char movebuf[sizeof SHIP(0)->file->movebuf];
80 int player;
81 struct ship *ms;		/* memorial structure, &cc->ship[player] */
82 struct File *mf;		/* ms->file */
83 struct shipspecs *mc;		/* ms->specs */
84 
85 void
86 initscreen(void)
87 {
88 	if (!SCREENTEST()) {
89 		printf("Can't sail on this terminal.\n");
90 		exit(1);
91 	}
92 	/* initscr() already done in SCREENTEST() */
93 	view_w = newwin(VIEW_Y, VIEW_X, VIEW_T, VIEW_L);
94 	slot_w = newwin(SLOT_Y, SLOT_X, SLOT_T, SLOT_L);
95 	scroll_w = newwin(SCROLL_Y, SCROLL_X, SCROLL_T, SCROLL_L);
96 	stat_w = newwin(STAT_Y, STAT_X, STAT_T, STAT_L);
97 	turn_w = newwin(TURN_Y, TURN_X, TURN_T, TURN_L);
98 	done_curses++;
99 	leaveok(view_w, 1);
100 	leaveok(slot_w, 1);
101 	leaveok(stat_w, 1);
102 	leaveok(turn_w, 1);
103 	noecho();
104 	cbreak();
105 }
106 
107 void
108 cleanupscreen(void)
109 {
110 	/* alarm already turned off */
111 	if (done_curses) {
112 		wmove(scroll_w, SCROLL_Y - 1, 0);
113 		wclrtoeol(scroll_w);
114 		draw_screen();
115 		endwin();
116 	}
117 }
118 
119 /*ARGSUSED*/
120 void
121 newturn(int n __attribute__((__unused__)))
122 {
123 	repaired = loaded = fired = changed = 0;
124 	movebuf[0] = '\0';
125 
126 	alarm(0);
127 	if (mf->readyL & R_LOADING) {
128 		if (mf->readyL & R_DOUBLE)
129 			mf->readyL = R_LOADING;
130 		else
131 			mf->readyL = R_LOADED;
132 	}
133 	if (mf->readyR & R_LOADING) {
134 		if (mf->readyR & R_DOUBLE)
135 			mf->readyR = R_LOADING;
136 		else
137 			mf->readyR = R_LOADED;
138 	}
139 	if (!hasdriver)
140 		Write(W_DDEAD, SHIP(0), 0, 0, 0, 0);
141 
142 	if (sc_hasprompt) {
143 		wmove(scroll_w, sc_line, 0);
144 		wclrtoeol(scroll_w);
145 	}
146 	if (Sync() < 0)
147 		leave(LEAVE_SYNC);
148 	if (!hasdriver)
149 		leave(LEAVE_DRIVER);
150 	if (sc_hasprompt)
151 		wprintw(scroll_w, "%s%s", sc_prompt, sc_buf);
152 
153 	if (turn % 50 == 0)
154 		Write(W_ALIVE, SHIP(0), 0, 0, 0, 0);
155 	if (mf->FS && (!mc->rig1 || windspeed == 6))
156 		Write(W_FS, ms, 0, 0, 0, 0);
157 	if (mf->FS == 1)
158 		Write(W_FS, ms, 2, 0, 0, 0);
159 
160 	if (mf->struck)
161 		leave(LEAVE_QUIT);
162 	if (mf->captured != 0)
163 		leave(LEAVE_CAPTURED);
164 	if (windspeed == 7)
165 		leave(LEAVE_HURRICAN);
166 
167 	adjustview();
168 	draw_screen();
169 
170 	signal(SIGALRM, newturn);
171 	alarm(7);
172 }
173 
174 /*VARARGS2*/
175 void
176 Signal(const char *fmt, struct ship *ship, ...)
177 {
178 	va_list ap;
179 	char format[BUFSIZ];
180 
181 	if (!done_curses)
182 		return;
183 	va_start(ap, ship);
184 	if (*fmt == '\7')
185 		putchar(*fmt++);
186 	fmtship(format, sizeof(format), fmt, ship);
187 	vwprintw(scroll_w, format, ap);
188 	va_end(ap);
189 	Scroll();
190 }
191 
192 /*VARARGS2*/
193 void
194 Msg(const char *fmt, ...)
195 {
196 	va_list ap;
197 
198 	if (!done_curses)
199 		return;
200 	va_start(ap, fmt);
201 	if (*fmt == '\7')
202 		putchar(*fmt++);
203 	vwprintw(scroll_w, fmt, ap);
204 	va_end(ap);
205 	Scroll();
206 }
207 
208 static void
209 Scroll(void)
210 {
211 	if (++sc_line >= SCROLL_Y)
212 		sc_line = 0;
213 	wmove(scroll_w, sc_line, 0);
214 	wclrtoeol(scroll_w);
215 }
216 
217 void
218 prompt(const char *p, struct ship *ship)
219 {
220 	static char buf[BUFSIZ];
221 
222 	fmtship(buf, sizeof(buf), p, ship);
223 	sc_prompt = buf;
224 	sc_buf = "";
225 	sc_hasprompt = 1;
226 	waddstr(scroll_w, buf);
227 }
228 
229 static void
230 endprompt(int flag)
231 {
232 	sc_hasprompt = 0;
233 	if (flag)
234 		Scroll();
235 }
236 
237 int
238 sgetch(const char *p, struct ship *ship, int flag)
239 {
240 	int c;
241 	prompt(p, ship);
242 	blockalarm();
243 	wrefresh(scroll_w);
244 	unblockalarm();
245 	while ((c = wgetch(scroll_w)) == EOF)
246 		;
247 	if (flag && c >= ' ' && c < 0x7f)
248 		waddch(scroll_w, c);
249 	endprompt(flag);
250 	return c;
251 }
252 
253 void
254 sgetstr(const char *pr, char *buf, int n)
255 {
256 	int c;
257 	char *p = buf;
258 
259 	prompt(pr, (struct ship *)0);
260 	sc_buf = buf;
261 	for (;;) {
262 		*p = 0;
263 		blockalarm();
264 		wrefresh(scroll_w);
265 		unblockalarm();
266 		while ((c = wgetch(scroll_w)) == EOF)
267 			;
268 		switch (c) {
269 		case '\n':
270 		case '\r':
271 			endprompt(1);
272 			return;
273 		case '\b':
274 			if (p > buf) {
275 				waddstr(scroll_w, "\b \b");
276 				p--;
277 			}
278 			break;
279 		default:
280 			if (c >= ' ' && c < 0x7f && p < buf + n - 1) {
281 				*p++ = c;
282 				waddch(scroll_w, c);
283 			} else
284 				putchar('\a');
285 		}
286 	}
287 }
288 
289 void
290 draw_screen(void)
291 {
292 	draw_view();
293 	draw_turn();
294 	draw_stat();
295 	draw_slot();
296 	wrefresh(scroll_w);		/* move the cursor */
297 }
298 
299 void
300 draw_view(void)
301 {
302 	struct ship *sp;
303 
304 	werase(view_w);
305 	foreachship(sp) {
306 		if (sp->file->dir
307 		    && sp->file->row > viewrow
308 		    && sp->file->row < viewrow + VIEW_Y
309 		    && sp->file->col > viewcol
310 		    && sp->file->col < viewcol + VIEW_X) {
311 			wmove(view_w, sp->file->row - viewrow,
312 				sp->file->col - viewcol);
313 			waddch(view_w, colours(sp));
314 			wmove(view_w,
315 				sternrow(sp) - viewrow,
316 				sterncol(sp) - viewcol);
317 			waddch(view_w, sterncolour(sp));
318 		}
319 	}
320 	wrefresh(view_w);
321 }
322 
323 void
324 draw_turn(void)
325 {
326 	wmove(turn_w, 0, 0);
327 	wprintw(turn_w, "%cTurn %d", dont_adjust?'*':'-', turn);
328 	wrefresh(turn_w);
329 }
330 
331 void
332 draw_stat(void)
333 {
334 	wmove(stat_w, STAT_1, 0);
335 	wprintw(stat_w, "Points  %3d\n", mf->points);
336 	wprintw(stat_w, "Fouls    %2d\n", fouled(ms));
337 	wprintw(stat_w, "Grapples %2d\n", grappled(ms));
338 
339 	wmove(stat_w, STAT_2, 0);
340 	wprintw(stat_w, "    0 %c(%c)\n",
341 		maxmove(ms, winddir + 3, -1) + '0',
342 		maxmove(ms, winddir + 3, 1) + '0');
343 	waddstr(stat_w, "   \\|/\n");
344 	wprintw(stat_w, "   -^-%c(%c)\n",
345 		maxmove(ms, winddir + 2, -1) + '0',
346 		maxmove(ms, winddir + 2, 1) + '0');
347 	waddstr(stat_w, "   /|\\\n");
348 	wprintw(stat_w, "    | %c(%c)\n",
349 		maxmove(ms, winddir + 1, -1) + '0',
350 		maxmove(ms, winddir + 1, 1) + '0');
351 	wprintw(stat_w, "   %c(%c)\n",
352 		maxmove(ms, winddir, -1) + '0',
353 		maxmove(ms, winddir, 1) + '0');
354 
355 	wmove(stat_w, STAT_3, 0);
356 	wprintw(stat_w, "Load  %c%c %c%c\n",
357 		loadname[mf->loadL], readyname(mf->readyL),
358 		loadname[mf->loadR], readyname(mf->readyR));
359 	wprintw(stat_w, "Hull %2d\n", mc->hull);
360 	wprintw(stat_w, "Crew %2d %2d %2d\n",
361 		mc->crew1, mc->crew2, mc->crew3);
362 	wprintw(stat_w, "Guns %2d %2d\n", mc->gunL, mc->gunR);
363 	wprintw(stat_w, "Carr %2d %2d\n", mc->carL, mc->carR);
364 	wprintw(stat_w, "Rigg %d %d %d ", mc->rig1, mc->rig2, mc->rig3);
365 	if (mc->rig4 < 0)
366 		waddch(stat_w, '-');
367 	else
368 		wprintw(stat_w, "%d", mc->rig4);
369 	wrefresh(stat_w);
370 }
371 
372 void
373 draw_slot(void)
374 {
375 	if (!boarding(ms, 0)) {
376 		mvwaddstr(slot_w, 0, 0, "   ");
377 		mvwaddstr(slot_w, 1, 0, "   ");
378 	} else
379 		mvwaddstr(slot_w, 1, 0, "OBP");
380 	if (!boarding(ms, 1)) {
381 		mvwaddstr(slot_w, 2, 0, "   ");
382 		mvwaddstr(slot_w, 3, 0, "   ");
383 	} else
384 		mvwaddstr(slot_w, 3, 0, "DBP");
385 
386 	wmove(slot_w, SLOT_Y-4, 0);
387 	if (mf->RH)
388 		wprintw(slot_w, "%dRH", mf->RH);
389 	else
390 		waddstr(slot_w, "   ");
391 	wmove(slot_w, SLOT_Y-3, 0);
392 	if (mf->RG)
393 		wprintw(slot_w, "%dRG", mf->RG);
394 	else
395 		waddstr(slot_w, "   ");
396 	wmove(slot_w, SLOT_Y-2, 0);
397 	if (mf->RR)
398 		wprintw(slot_w, "%dRR", mf->RR);
399 	else
400 		waddstr(slot_w, "   ");
401 
402 #define Y	(SLOT_Y/2)
403 	wmove(slot_w, 7, 1);
404 	wprintw(slot_w,"%d", windspeed);
405 	mvwaddch(slot_w, Y, 0, ' ');
406 	mvwaddch(slot_w, Y, 2, ' ');
407 	mvwaddch(slot_w, Y-1, 0, ' ');
408 	mvwaddch(slot_w, Y-1, 1, ' ');
409 	mvwaddch(slot_w, Y-1, 2, ' ');
410 	mvwaddch(slot_w, Y+1, 0, ' ');
411 	mvwaddch(slot_w, Y+1, 1, ' ');
412 	mvwaddch(slot_w, Y+1, 2, ' ');
413 	wmove(slot_w, Y - dr[winddir], 1 - dc[winddir]);
414 	switch (winddir) {
415 	case 1:
416 	case 5:
417 		waddch(slot_w, '|');
418 		break;
419 	case 2:
420 	case 6:
421 		waddch(slot_w, '/');
422 		break;
423 	case 3:
424 	case 7:
425 		waddch(slot_w, '-');
426 		break;
427 	case 4:
428 	case 8:
429 		waddch(slot_w, '\\');
430 		break;
431 	}
432 	mvwaddch(slot_w, Y + dr[winddir], 1 + dc[winddir], '+');
433 	wrefresh(slot_w);
434 }
435 
436 void
437 draw_board(void)
438 {
439 	int n;
440 
441 	clear();
442 	werase(view_w);
443 	werase(slot_w);
444 	werase(scroll_w);
445 	werase(stat_w);
446 	werase(turn_w);
447 
448 	sc_line = 0;
449 
450 	move(BOX_T, BOX_L);
451 	for (n = 0; n < BOX_X; n++)
452 		addch('-');
453 	move(BOX_B, BOX_L);
454 	for (n = 0; n < BOX_X; n++)
455 		addch('-');
456 	for (n = BOX_T+1; n < BOX_B; n++) {
457 		mvaddch(n, BOX_L, '|');
458 		mvaddch(n, BOX_R, '|');
459 	}
460 	mvaddch(BOX_T, BOX_L, '+');
461 	mvaddch(BOX_T, BOX_R, '+');
462 	mvaddch(BOX_B, BOX_L, '+');
463 	mvaddch(BOX_B, BOX_R, '+');
464 	refresh();
465 
466 #define WSaIM "Wooden Ships & Iron Men"
467 	wmove(view_w, 2, (VIEW_X - sizeof WSaIM - 1) / 2);
468 	waddstr(view_w, WSaIM);
469 	wmove(view_w, 4, (VIEW_X - strlen(cc->name)) / 2);
470 	waddstr(view_w, cc->name);
471 	wrefresh(view_w);
472 
473 	move(LINE_T, LINE_L);
474 	printw("Class %d %s (%d guns) '%s' (%c%c)",
475 		mc->class,
476 		classname[mc->class],
477 		mc->guns,
478 		ms->shipname,
479 		colours(ms),
480 		sterncolour(ms));
481 	refresh();
482 }
483 
484 void
485 centerview(void)
486 {
487 	viewrow = mf->row - VIEW_Y / 2;
488 	viewcol = mf->col - VIEW_X / 2;
489 }
490 
491 void
492 upview(void)
493 {
494 	viewrow -= VIEW_Y / 3;
495 }
496 
497 void
498 downview(void)
499 {
500 	viewrow += VIEW_Y / 3;
501 }
502 
503 void
504 leftview(void)
505 {
506 	viewcol -= VIEW_X / 5;
507 }
508 
509 void
510 rightview(void)
511 {
512 	viewcol += VIEW_X / 5;
513 }
514 
515 static void
516 adjustview(void)
517 {
518 	if (dont_adjust)
519 		return;
520 	if (mf->row < viewrow + VIEW_Y/4)
521 		viewrow = mf->row - (VIEW_Y - VIEW_Y/4);
522 	else if (mf->row > viewrow + (VIEW_Y - VIEW_Y/4))
523 		viewrow = mf->row - VIEW_Y/4;
524 	if (mf->col < viewcol + VIEW_X/8)
525 		viewcol = mf->col - (VIEW_X - VIEW_X/8);
526 	else if (mf->col > viewcol + (VIEW_X - VIEW_X/8))
527 		viewcol = mf->col - VIEW_X/8;
528 }
529