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