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