pl_7.c revision 1.22 1 /* $NetBSD: pl_7.c,v 1.22 2001/01/04 06:33:18 itojun 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.22 2001/01/04 06:33:18 itojun 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 <unistd.h>
50 #include <string.h>
51 #include "extern.h"
52 #include "player.h"
53 #include "display.h"
54
55 void initscreen(void);
56 void cleanupscreen(void);
57 void newturn(int);
58 void Signal(const char *, struct ship *, ...)
59 __attribute__((__format__(__printf__,1,3)));
60 void Msg(const char *, ...)
61 __attribute__((__format__(__printf__,1,2)));
62 static void Scroll(void);
63 void prompt(const char *, struct ship *);
64 static void endprompt(int);
65 int sgetch(const char *, struct ship *, int);
66 void sgetstr(const char *, char *, int);
67 void draw_screen(void);
68 void draw_view(void);
69 void draw_turn(void);
70 void draw_stat(void);
71 void draw_slot(void);
72 void draw_board(void);
73 void centerview(void);
74 void upview(void);
75 void downview(void);
76 void leftview(void);
77 void rightview(void);
78 static void adjustview(void);
79
80 /*
81 * Display interface
82 */
83
84 static char sc_hasprompt;
85 static const char *sc_prompt;
86 static const char *sc_buf;
87 static int sc_line;
88
89 WINDOW *view_w;
90 WINDOW *slot_w;
91 WINDOW *scroll_w;
92 WINDOW *stat_w;
93 WINDOW *turn_w;
94
95 int done_curses;
96 int loaded, fired, changed, repaired;
97 int dont_adjust;
98 int viewrow, viewcol;
99 char movebuf[sizeof SHIP(0)->file->movebuf];
100 int player;
101 struct ship *ms; /* memorial structure, &cc->ship[player] */
102 struct File *mf; /* ms->file */
103 struct shipspecs *mc; /* ms->specs */
104
105 void
106 initscreen(void)
107 {
108 if (!SCREENTEST()) {
109 printf("Can't sail on this terminal.\n");
110 exit(1);
111 }
112 /* initscr() already done in SCREENTEST() */
113 view_w = newwin(VIEW_Y, VIEW_X, VIEW_T, VIEW_L);
114 slot_w = newwin(SLOT_Y, SLOT_X, SLOT_T, SLOT_L);
115 scroll_w = newwin(SCROLL_Y, SCROLL_X, SCROLL_T, SCROLL_L);
116 stat_w = newwin(STAT_Y, STAT_X, STAT_T, STAT_L);
117 turn_w = newwin(TURN_Y, TURN_X, TURN_T, TURN_L);
118 done_curses++;
119 leaveok(view_w, 1);
120 leaveok(slot_w, 1);
121 leaveok(stat_w, 1);
122 leaveok(turn_w, 1);
123 noecho();
124 crmode();
125 }
126
127 void
128 cleanupscreen(void)
129 {
130 /* alarm already turned off */
131 if (done_curses) {
132 wmove(scroll_w, SCROLL_Y - 1, 0);
133 wclrtoeol(scroll_w);
134 draw_screen();
135 endwin();
136 }
137 }
138
139 /*ARGSUSED*/
140 void
141 newturn(int n __attribute__((__unused__)))
142 {
143 repaired = loaded = fired = changed = 0;
144 movebuf[0] = '\0';
145
146 alarm(0);
147 if (mf->readyL & R_LOADING) {
148 if (mf->readyL & R_DOUBLE)
149 mf->readyL = R_LOADING;
150 else
151 mf->readyL = R_LOADED;
152 }
153 if (mf->readyR & R_LOADING) {
154 if (mf->readyR & R_DOUBLE)
155 mf->readyR = R_LOADING;
156 else
157 mf->readyR = R_LOADED;
158 }
159 if (!hasdriver)
160 Write(W_DDEAD, SHIP(0), 0, 0, 0, 0);
161
162 if (sc_hasprompt) {
163 wmove(scroll_w, sc_line, 0);
164 wclrtoeol(scroll_w);
165 }
166 if (Sync() < 0)
167 leave(LEAVE_SYNC);
168 if (!hasdriver)
169 leave(LEAVE_DRIVER);
170 if (sc_hasprompt)
171 wprintw(scroll_w, "%s%s", sc_prompt, sc_buf);
172
173 if (turn % 50 == 0)
174 Write(W_ALIVE, SHIP(0), 0, 0, 0, 0);
175 if (mf->FS && (!mc->rig1 || windspeed == 6))
176 Write(W_FS, ms, 0, 0, 0, 0);
177 if (mf->FS == 1)
178 Write(W_FS, ms, 2, 0, 0, 0);
179
180 if (mf->struck)
181 leave(LEAVE_QUIT);
182 if (mf->captured != 0)
183 leave(LEAVE_CAPTURED);
184 if (windspeed == 7)
185 leave(LEAVE_HURRICAN);
186
187 adjustview();
188 draw_screen();
189
190 signal(SIGALRM, newturn);
191 alarm(7);
192 }
193
194 /*VARARGS2*/
195 void
196 Signal(const char *fmt, struct ship *ship, ...)
197 {
198 va_list ap;
199 char format[BUFSIZ];
200
201 va_start(ap, ship);
202 if (!done_curses)
203 return;
204 if (*fmt == '\7')
205 putchar(*fmt++);
206 fmtship(format, sizeof(format), fmt, ship);
207 vwprintw(scroll_w, format, ap);
208 va_end(ap);
209 Scroll();
210 }
211
212 /*VARARGS2*/
213 void
214 Msg(const char *fmt, ...)
215 {
216 va_list ap;
217
218 va_start(ap, fmt);
219 if (!done_curses)
220 return;
221 if (*fmt == '\7')
222 putchar(*fmt++);
223 vwprintw(scroll_w, fmt, ap);
224 va_end(ap);
225 Scroll();
226 }
227
228 static void
229 Scroll(void)
230 {
231 if (++sc_line >= SCROLL_Y)
232 sc_line = 0;
233 wmove(scroll_w, sc_line, 0);
234 wclrtoeol(scroll_w);
235 }
236
237 void
238 prompt(const char *p, struct ship *ship)
239 {
240 static char buf[BUFSIZ];
241
242 fmtship(buf, sizeof(buf), p, ship);
243 sc_prompt = buf;
244 sc_buf = "";
245 sc_hasprompt = 1;
246 waddstr(scroll_w, buf);
247 }
248
249 static void
250 endprompt(int flag)
251 {
252 sc_hasprompt = 0;
253 if (flag)
254 Scroll();
255 }
256
257 int
258 sgetch(const char *p, struct ship *ship, int flag)
259 {
260 int c;
261 prompt(p, ship);
262 blockalarm();
263 wrefresh(scroll_w);
264 unblockalarm();
265 while ((c = wgetch(scroll_w)) == EOF)
266 ;
267 if (flag && c >= ' ' && c < 0x7f)
268 waddch(scroll_w, c);
269 endprompt(flag);
270 return c;
271 }
272
273 void
274 sgetstr(const char *pr, char *buf, int n)
275 {
276 int c;
277 char *p = buf;
278
279 prompt(pr, (struct ship *)0);
280 sc_buf = buf;
281 for (;;) {
282 *p = 0;
283 blockalarm();
284 wrefresh(scroll_w);
285 unblockalarm();
286 while ((c = wgetch(scroll_w)) == EOF)
287 ;
288 switch (c) {
289 case '\n':
290 case '\r':
291 endprompt(1);
292 return;
293 case '\b':
294 if (p > buf) {
295 waddstr(scroll_w, "\b \b");
296 p--;
297 }
298 break;
299 default:
300 if (c >= ' ' && c < 0x7f && p < buf + n - 1) {
301 *p++ = c;
302 waddch(scroll_w, c);
303 } else
304 putchar('\a');
305 }
306 }
307 }
308
309 void
310 draw_screen(void)
311 {
312 draw_view();
313 draw_turn();
314 draw_stat();
315 draw_slot();
316 wrefresh(scroll_w); /* move the cursor */
317 }
318
319 void
320 draw_view(void)
321 {
322 struct ship *sp;
323
324 werase(view_w);
325 foreachship(sp) {
326 if (sp->file->dir
327 && sp->file->row > viewrow
328 && sp->file->row < viewrow + VIEW_Y
329 && sp->file->col > viewcol
330 && sp->file->col < viewcol + VIEW_X) {
331 wmove(view_w, sp->file->row - viewrow,
332 sp->file->col - viewcol);
333 waddch(view_w, colours(sp));
334 wmove(view_w,
335 sternrow(sp) - viewrow,
336 sterncol(sp) - viewcol);
337 waddch(view_w, sterncolour(sp));
338 }
339 }
340 wrefresh(view_w);
341 }
342
343 void
344 draw_turn(void)
345 {
346 wmove(turn_w, 0, 0);
347 wprintw(turn_w, "%cTurn %d", dont_adjust?'*':'-', turn);
348 wrefresh(turn_w);
349 }
350
351 void
352 draw_stat(void)
353 {
354 wmove(stat_w, STAT_1, 0);
355 wprintw(stat_w, "Points %3d\n", mf->points);
356 wprintw(stat_w, "Fouls %2d\n", fouled(ms));
357 wprintw(stat_w, "Grapples %2d\n", grappled(ms));
358
359 wmove(stat_w, STAT_2, 0);
360 wprintw(stat_w, " 0 %c(%c)\n",
361 maxmove(ms, winddir + 3, -1) + '0',
362 maxmove(ms, winddir + 3, 1) + '0');
363 waddstr(stat_w, " \\|/\n");
364 wprintw(stat_w, " -^-%c(%c)\n",
365 maxmove(ms, winddir + 2, -1) + '0',
366 maxmove(ms, winddir + 2, 1) + '0');
367 waddstr(stat_w, " /|\\\n");
368 wprintw(stat_w, " | %c(%c)\n",
369 maxmove(ms, winddir + 1, -1) + '0',
370 maxmove(ms, winddir + 1, 1) + '0');
371 wprintw(stat_w, " %c(%c)\n",
372 maxmove(ms, winddir, -1) + '0',
373 maxmove(ms, winddir, 1) + '0');
374
375 wmove(stat_w, STAT_3, 0);
376 wprintw(stat_w, "Load %c%c %c%c\n",
377 loadname[mf->loadL], readyname(mf->readyL),
378 loadname[mf->loadR], readyname(mf->readyR));
379 wprintw(stat_w, "Hull %2d\n", mc->hull);
380 wprintw(stat_w, "Crew %2d %2d %2d\n",
381 mc->crew1, mc->crew2, mc->crew3);
382 wprintw(stat_w, "Guns %2d %2d\n", mc->gunL, mc->gunR);
383 wprintw(stat_w, "Carr %2d %2d\n", mc->carL, mc->carR);
384 wprintw(stat_w, "Rigg %d %d %d ", mc->rig1, mc->rig2, mc->rig3);
385 if (mc->rig4 < 0)
386 waddch(stat_w, '-');
387 else
388 wprintw(stat_w, "%d", mc->rig4);
389 wrefresh(stat_w);
390 }
391
392 void
393 draw_slot(void)
394 {
395 if (!boarding(ms, 0)) {
396 mvwaddstr(slot_w, 0, 0, " ");
397 mvwaddstr(slot_w, 1, 0, " ");
398 } else
399 mvwaddstr(slot_w, 1, 0, "OBP");
400 if (!boarding(ms, 1)) {
401 mvwaddstr(slot_w, 2, 0, " ");
402 mvwaddstr(slot_w, 3, 0, " ");
403 } else
404 mvwaddstr(slot_w, 3, 0, "DBP");
405
406 wmove(slot_w, SLOT_Y-4, 0);
407 if (mf->RH)
408 wprintw(slot_w, "%dRH", mf->RH);
409 else
410 waddstr(slot_w, " ");
411 wmove(slot_w, SLOT_Y-3, 0);
412 if (mf->RG)
413 wprintw(slot_w, "%dRG", mf->RG);
414 else
415 waddstr(slot_w, " ");
416 wmove(slot_w, SLOT_Y-2, 0);
417 if (mf->RR)
418 wprintw(slot_w, "%dRR", mf->RR);
419 else
420 waddstr(slot_w, " ");
421
422 #define Y (SLOT_Y/2)
423 wmove(slot_w, 7, 1);
424 wprintw(slot_w,"%d", windspeed);
425 mvwaddch(slot_w, Y, 0, ' ');
426 mvwaddch(slot_w, Y, 2, ' ');
427 mvwaddch(slot_w, Y-1, 0, ' ');
428 mvwaddch(slot_w, Y-1, 1, ' ');
429 mvwaddch(slot_w, Y-1, 2, ' ');
430 mvwaddch(slot_w, Y+1, 0, ' ');
431 mvwaddch(slot_w, Y+1, 1, ' ');
432 mvwaddch(slot_w, Y+1, 2, ' ');
433 wmove(slot_w, Y - dr[winddir], 1 - dc[winddir]);
434 switch (winddir) {
435 case 1:
436 case 5:
437 waddch(slot_w, '|');
438 break;
439 case 2:
440 case 6:
441 waddch(slot_w, '/');
442 break;
443 case 3:
444 case 7:
445 waddch(slot_w, '-');
446 break;
447 case 4:
448 case 8:
449 waddch(slot_w, '\\');
450 break;
451 }
452 mvwaddch(slot_w, Y + dr[winddir], 1 + dc[winddir], '+');
453 wrefresh(slot_w);
454 }
455
456 void
457 draw_board(void)
458 {
459 int n;
460
461 clear();
462 werase(view_w);
463 werase(slot_w);
464 werase(scroll_w);
465 werase(stat_w);
466 werase(turn_w);
467
468 sc_line = 0;
469
470 move(BOX_T, BOX_L);
471 for (n = 0; n < BOX_X; n++)
472 addch('-');
473 move(BOX_B, BOX_L);
474 for (n = 0; n < BOX_X; n++)
475 addch('-');
476 for (n = BOX_T+1; n < BOX_B; n++) {
477 mvaddch(n, BOX_L, '|');
478 mvaddch(n, BOX_R, '|');
479 }
480 mvaddch(BOX_T, BOX_L, '+');
481 mvaddch(BOX_T, BOX_R, '+');
482 mvaddch(BOX_B, BOX_L, '+');
483 mvaddch(BOX_B, BOX_R, '+');
484 refresh();
485
486 #define WSaIM "Wooden Ships & Iron Men"
487 wmove(view_w, 2, (VIEW_X - sizeof WSaIM - 1) / 2);
488 waddstr(view_w, WSaIM);
489 wmove(view_w, 4, (VIEW_X - strlen(cc->name)) / 2);
490 waddstr(view_w, cc->name);
491 wrefresh(view_w);
492
493 move(LINE_T, LINE_L);
494 printw("Class %d %s (%d guns) '%s' (%c%c)",
495 mc->class,
496 classname[mc->class],
497 mc->guns,
498 ms->shipname,
499 colours(ms),
500 sterncolour(ms));
501 refresh();
502 }
503
504 void
505 centerview(void)
506 {
507 viewrow = mf->row - VIEW_Y / 2;
508 viewcol = mf->col - VIEW_X / 2;
509 }
510
511 void
512 upview(void)
513 {
514 viewrow -= VIEW_Y / 3;
515 }
516
517 void
518 downview(void)
519 {
520 viewrow += VIEW_Y / 3;
521 }
522
523 void
524 leftview(void)
525 {
526 viewcol -= VIEW_X / 5;
527 }
528
529 void
530 rightview(void)
531 {
532 viewcol += VIEW_X / 5;
533 }
534
535 static void
536 adjustview(void)
537 {
538 if (dont_adjust)
539 return;
540 if (mf->row < viewrow + VIEW_Y/4)
541 viewrow = mf->row - (VIEW_Y - VIEW_Y/4);
542 else if (mf->row > viewrow + (VIEW_Y - VIEW_Y/4))
543 viewrow = mf->row - VIEW_Y/4;
544 if (mf->col < viewcol + VIEW_X/8)
545 viewcol = mf->col - (VIEW_X - VIEW_X/8);
546 else if (mf->col > viewcol + (VIEW_X - VIEW_X/8))
547 viewcol = mf->col - VIEW_X/8;
548 }
549