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