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