Annotation of early-roguelike/arogue7/io.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * io.c - Various input/output functions
! 3: *
! 4: * Advanced Rogue
! 5: * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
! 6: * All rights reserved.
! 7: *
! 8: * Based on "Rogue: Exploring the Dungeons of Doom"
! 9: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 10: * All rights reserved.
! 11: *
! 12: * See the file LICENSE.TXT for full copyright and licensing information.
! 13: */
! 14:
! 15: /*
! 16: * Various input/output functions
! 17: */
! 18:
! 19: #include "curses.h"
! 20: #include <stdarg.h>
! 21: #include <ctype.h>
! 22: #include <string.h>
! 23: #include "rogue.h"
! 24:
! 25: /*
! 26: * msg:
! 27: * Display a message at the top of the screen.
! 28: */
! 29:
! 30: static char msgbuf[BUFSIZ];
! 31: static int newpos = 0;
! 32:
! 33: void doadd(char *fmt, va_list ap);
! 34:
! 35: /*VARARGS1*/
! 36: void
! 37: msg(char *fmt, ...)
! 38: {
! 39: va_list ap;
! 40: /*
! 41: * if the string is "", just clear the line
! 42: */
! 43: if (*fmt == '\0')
! 44: {
! 45: overwrite(cw,msgw);
! 46: wmove(msgw, 0, 0);
! 47: clearok(msgw, FALSE);
! 48: draw(msgw);
! 49: mpos = 0;
! 50: return;
! 51: }
! 52: /*
! 53: * otherwise add to the message and flush it out
! 54: */
! 55: va_start(ap,fmt);
! 56: doadd(fmt, ap);
! 57: va_end(ap);
! 58: endmsg();
! 59: }
! 60:
! 61: /*
! 62: * add things to the current message
! 63: */
! 64: void
! 65: addmsg(char *fmt, ...)
! 66: {
! 67: va_list ap;
! 68:
! 69: va_start(ap, fmt);
! 70: doadd(fmt, ap);
! 71: va_end(ap);
! 72: }
! 73:
! 74: /*
! 75: * Display a new msg (giving him a chance to see the previous one if it
! 76: * is up there with the --More--)
! 77: */
! 78: void
! 79: endmsg(void)
! 80: {
! 81: /* Needed to track where we are for 5.0 (PC) curses */
! 82: register int x, y;
! 83:
! 84: strcpy(huh, msgbuf);
! 85: if (mpos) {
! 86: /*
! 87: * If this message will fit on the line (plus space for --More--
! 88: * then just add it (only during combat).
! 89: */
! 90: if (player.t_quiet < 0 && mpos + newpos + strlen(morestr) + 2 < cols) {
! 91: wmove(msgw, 0, mpos + 2);
! 92: newpos += mpos + 2;
! 93: }
! 94: else {
! 95: wmove(msgw, 0, mpos);
! 96: waddstr(msgw, morestr);
! 97: draw(cw);
! 98: draw(msgw);
! 99: wait_for(' ');
! 100: overwrite(cw,msgw);
! 101: wmove(msgw, 0, 0);
! 102: touchwin(cw);
! 103: }
! 104: }
! 105: else {
! 106: overwrite(cw,msgw);
! 107: wmove(msgw, 0, 0);
! 108: }
! 109: waddstr(msgw, msgbuf);
! 110: getyx(msgw, y, x);
! 111: mpos = newpos;
! 112: newpos = 0;
! 113: wmove(msgw, y, x);
! 114: draw(cw);
! 115: clearok(msgw, FALSE);
! 116: draw(msgw);
! 117: }
! 118:
! 119: void
! 120: doadd(char *fmt, va_list ap)
! 121: {
! 122:
! 123: /*
! 124: * Do the printf into buf
! 125: */
! 126: vsprintf(&msgbuf[newpos], fmt, ap);
! 127: newpos = strlen(msgbuf);
! 128: }
! 129:
! 130: /*
! 131: * step_ok:
! 132: * returns true if it is ok for type to step on ch
! 133: * flgptr will be NULL if we don't know what the monster is yet!
! 134: */
! 135:
! 136: bool
! 137: step_ok(int y, int x, int can_on_monst, struct thing *flgptr)
! 138: {
! 139: /* can_on_monst = MONSTOK if all we care about are physical obstacles */
! 140: register struct linked_list *item;
! 141: register struct thing *tp;
! 142: char ch;
! 143:
! 144: /* What is here? Don't check monster window if MONSTOK is set */
! 145: if (can_on_monst == MONSTOK) ch = CCHAR( mvinch(y, x) );
! 146: else ch = CCHAR( winat(y, x) );
! 147:
! 148: if (can_on_monst == FIGHTOK && isalpha(ch) &&
! 149: (item = find_mons(y, x)) != NULL) {
! 150: tp = THINGPTR(item); /* What monster is here? */
! 151:
! 152: /* We can hit it if we're after it */
! 153: if (flgptr->t_dest == &tp->t_pos) return TRUE;
! 154:
! 155: /*
! 156: * Otherwise, if we're friendly we'll hit it unless it is also
! 157: * friendly or is our race.
! 158: */
! 159: if (off(*flgptr, ISFRIENDLY) ||
! 160: on(*tp, ISFRIENDLY) ||
! 161: flgptr->t_index == tp->t_index) return FALSE;
! 162: else return TRUE;
! 163: }
! 164: else switch (ch)
! 165: {
! 166: case ' ':
! 167: case '|':
! 168: case '-':
! 169: case SECRETDOOR:
! 170: if (flgptr && on(*flgptr, CANINWALL)) return(TRUE);
! 171: return FALSE;
! 172: when SCROLL:
! 173: if (can_on_monst == MONSTOK) return(TRUE); /* Not a real obstacle */
! 174: /*
! 175: * If it is a scroll, it might be a scare monster scroll
! 176: * so we need to look it up to see what type it is.
! 177: */
! 178: if (flgptr && flgptr->t_ctype == C_MONSTER) {
! 179: item = find_obj(y, x);
! 180: if (item != NULL &&
! 181: (OBJPTR(item))->o_which==S_SCARE &&
! 182: (flgptr == NULL || flgptr->t_stats.s_intel < 16))
! 183: return(FALSE); /* All but smart ones are scared */
! 184: }
! 185: return(TRUE);
! 186: otherwise:
! 187: return (!isalpha(ch));
! 188: }
! 189: return(FALSE);
! 190: }
! 191: /*
! 192: * shoot_ok:
! 193: * returns true if it is ok for type to shoot over ch
! 194: */
! 195:
! 196: bool
! 197: shoot_ok(char ch)
! 198: {
! 199: switch (ch)
! 200: {
! 201: case ' ':
! 202: case '|':
! 203: case '-':
! 204: case SECRETDOOR:
! 205: case FOREST:
! 206: return FALSE;
! 207: default:
! 208: return (!isalpha(ch));
! 209: }
! 210: }
! 211:
! 212: /*
! 213: * readchar:
! 214: * flushes stdout so that screen is up to date and then returns
! 215: * getchar.
! 216: */
! 217:
! 218: int
! 219: readchar(void)
! 220: {
! 221: int ch;
! 222:
! 223: ch = md_readchar(cw);
! 224:
! 225: if ((ch == 3) || (ch == 0))
! 226: {
! 227: quit(0);
! 228: return(27);
! 229: }
! 230:
! 231: return(ch);
! 232: }
! 233:
! 234: /*
! 235: * status:
! 236: * Display the important stats line. Keep the cursor where it was.
! 237: * display: if TRUE, display unconditionally
! 238: */
! 239:
! 240: void
! 241: status(bool display)
! 242: {
! 243: register struct stats *stat_ptr, *max_ptr;
! 244: register int oy, ox, temp;
! 245: register char *pb;
! 246: static char buf[LINELEN];
! 247: static int hpwidth = 0, s_hungry = -1;
! 248: static int s_lvl = -1, s_hp = -1, s_str, maxs_str,
! 249: s_ac = 0;
! 250: static short s_intel, s_dext, s_wisdom, s_const, s_charisma;
! 251: static short maxs_intel, maxs_dext, maxs_wisdom, maxs_const, maxs_charisma;
! 252: static unsigned long s_exp = 0;
! 253: static int s_carry, s_pack;
! 254: bool first_line=FALSE;
! 255:
! 256: stat_ptr = &pstats;
! 257: max_ptr = &max_stats;
! 258:
! 259: /*
! 260: * If nothing has changed in the first line, then skip it
! 261: */
! 262: if (!display &&
! 263: s_lvl == level &&
! 264: s_intel == stat_ptr->s_intel &&
! 265: s_wisdom == stat_ptr->s_wisdom &&
! 266: s_dext == dex_compute() &&
! 267: s_const == stat_ptr->s_const &&
! 268: s_charisma == stat_ptr->s_charisma &&
! 269: s_str == str_compute() &&
! 270: s_hungry == hungry_state &&
! 271: maxs_intel == max_ptr->s_intel &&
! 272: maxs_wisdom == max_ptr->s_wisdom &&
! 273: maxs_dext == max_ptr->s_dext &&
! 274: maxs_const == max_ptr->s_const &&
! 275: maxs_charisma == max_ptr->s_charisma &&
! 276: maxs_str == max_ptr->s_str ) goto line_two;
! 277:
! 278: /* Display the first line */
! 279: first_line = TRUE;
! 280: getyx(cw, oy, ox);
! 281: sprintf(buf, "Int:%d(%d) Str:%d", stat_ptr->s_intel,
! 282: max_ptr->s_intel, str_compute());
! 283:
! 284: /* Maximum strength */
! 285: pb = &buf[strlen(buf)];
! 286: sprintf(pb, "(%d)", max_ptr->s_str);
! 287:
! 288: pb = &buf[strlen(buf)];
! 289: sprintf(pb, " Wis:%d(%d) Dxt:%d(%d) Con:%d(%d) Cha:%d(%d)",
! 290: stat_ptr->s_wisdom,max_ptr->s_wisdom,dex_compute(),max_ptr->s_dext,
! 291: stat_ptr->s_const,max_ptr->s_const,stat_ptr->s_charisma,
! 292: max_ptr->s_charisma);
! 293:
! 294: /* Update first line status */
! 295: s_intel = stat_ptr->s_intel;
! 296: s_wisdom = stat_ptr->s_wisdom;
! 297: s_dext = dex_compute();
! 298: s_const = stat_ptr->s_const;
! 299: s_charisma = stat_ptr->s_charisma;
! 300: s_str = str_compute();
! 301: maxs_intel = max_ptr->s_intel;
! 302: maxs_wisdom = max_ptr->s_wisdom;
! 303: maxs_dext = max_ptr->s_dext;
! 304: maxs_const = max_ptr->s_const;
! 305: maxs_charisma = max_ptr->s_charisma;
! 306: maxs_str = max_ptr->s_str;
! 307:
! 308: /* Print the line */
! 309: mvwaddstr(cw, lines - 2, 0, buf);
! 310: switch (hungry_state)
! 311: {
! 312: case F_SATIATED:
! 313: waddstr(cw, " Satiated");
! 314: when F_OKAY: ;
! 315: when F_HUNGRY:
! 316: waddstr(cw, " Hungry");
! 317: when F_WEAK:
! 318: waddstr(cw, " Weak");
! 319: when F_FAINT:
! 320: waddstr(cw, " Fainting");
! 321: }
! 322: wclrtoeol(cw);
! 323: s_hungry = hungry_state;
! 324:
! 325: /*
! 326: * If nothing has changed since the last status, don't
! 327: * bother.
! 328: */
! 329: line_two:
! 330: if (!display &&
! 331: s_lvl == level &&
! 332: s_hp == stat_ptr->s_hpt &&
! 333: s_ac == ac_compute(FALSE) - dext_prot(s_dext) &&
! 334: s_pack == stat_ptr->s_pack &&
! 335: s_carry == stat_ptr->s_carry &&
! 336: s_exp == stat_ptr->s_exp ) return;
! 337:
! 338: if (!first_line) getyx(cw, oy, ox);
! 339: if (s_hp != max_ptr->s_hpt)
! 340: {
! 341: temp = s_hp = max_ptr->s_hpt;
! 342: for (hpwidth = 0; temp; hpwidth++)
! 343: temp /= 10;
! 344: }
! 345: sprintf(buf, "Lvl:%d Hp:%*d(%*d) Ac:%d Carry:%d(%d) Exp:%d/%lu %s",
! 346: level, hpwidth, stat_ptr->s_hpt, hpwidth, max_ptr->s_hpt,
! 347: ac_compute(FALSE) - dext_prot(s_dext),stat_ptr->s_pack/10,
! 348: stat_ptr->s_carry/10, stat_ptr->s_lvl, stat_ptr->s_exp,
! 349: cnames[player.t_ctype][min(stat_ptr->s_lvl-1, NUM_CNAMES-1)]);
! 350:
! 351: /*
! 352: * Save old status
! 353: */
! 354: s_lvl = level;
! 355: s_hp = stat_ptr->s_hpt;
! 356: s_ac = ac_compute(FALSE) - dext_prot(s_dext);
! 357: s_pack = stat_ptr->s_pack;
! 358: s_carry = stat_ptr->s_carry;
! 359: s_exp = stat_ptr->s_exp;
! 360: mvwaddstr(cw, lines - 1, 0, buf);
! 361: wclrtoeol(cw);
! 362: wmove(cw, oy, ox);
! 363: }
! 364:
! 365: /*
! 366: * wait_for
! 367: * Sit around until the guy types the right key
! 368: */
! 369: void
! 370: wait_for(char ch)
! 371: {
! 372: register char c;
! 373:
! 374: if (ch == '\n')
! 375: while ((c = wgetch(msgw)) != '\n' && c != '\r')
! 376: continue;
! 377: else
! 378: while (wgetch(msgw) != ch)
! 379: continue;
! 380: }
! 381:
! 382:
! 383: /*
! 384: * over_win:
! 385: * Given a current window, a new window, and the max y and x of the
! 386: * new window, paint the new window on top of the old window without
! 387: * destroying any of the old window. Current window and new window
! 388: * are assumed to have lines lines and cols columns (max y and max x
! 389: * pertain only the the useful information to be displayed.
! 390: * If redraw is non-zero, we wait for the character "redraw" to be
! 391: * typed and then redraw the starting screen.
! 392: */
! 393:
! 394: void
! 395: over_win(WINDOW *oldwin, WINDOW *newin, int maxy, int maxx, int cursory,
! 396: int cursorx, char redraw)
! 397: {
! 398: static char blanks[LINELEN+1];
! 399: register int line, i;
! 400: WINDOW *ow; /* Overlay window */
! 401:
! 402: /* Create a blanking line */
! 403: for (i=0; i<maxx && i<cols && i<LINELEN; i++) blanks[i] = ' ';
! 404: blanks[i] = '\0';
! 405:
! 406: /* Create the window we will display */
! 407: ow = newwin(lines, cols, 0, 0);
! 408:
! 409: /* Blank out the area we want to use */
! 410: if (oldwin == cw) {
! 411: msg("");
! 412: line = 1;
! 413: }
! 414: else line = 0;
! 415:
! 416: overwrite(oldwin, ow); /* Get a copy of the old window */
! 417:
! 418: /* Do the remaining blanking */
! 419: for (; line < maxy; line++) mvwaddstr(ow, line, 0, blanks);
! 420:
! 421: overlay(newin, ow); /* Overlay our new window */
! 422:
! 423: /* Move the cursor to the specified location */
! 424: wmove(ow, cursory, cursorx);
! 425:
! 426: clearok(ow, FALSE); /* Draw inventory without clearing */
! 427: draw(ow);
! 428:
! 429: if (redraw) {
! 430: wait_for(redraw);
! 431:
! 432: clearok(oldwin, FALSE); /* Setup to redraw current screen */
! 433: touchwin(oldwin); /* clearing first */
! 434: draw(oldwin);
! 435: }
! 436:
! 437: delwin(ow);
! 438: }
! 439:
! 440:
! 441: /*
! 442: * show_win:
! 443: * function used to display a window and wait before returning
! 444: */
! 445:
! 446: void
! 447: show_win(WINDOW *scr, char *message)
! 448: {
! 449: mvwaddstr(scr, 0, 0, message);
! 450: touchwin(scr);
! 451: wmove(scr, hero.y, hero.x);
! 452: draw(scr);
! 453: wait_for(' ');
! 454: clearok(cw, TRUE);
! 455: touchwin(cw);
! 456: }
! 457:
! 458: /*
! 459: * dbotline:
! 460: * Displays message on bottom line and waits for a space to return
! 461: */
! 462: void
! 463: dbotline(WINDOW *scr, char *message)
! 464: {
! 465: mvwaddstr(scr,lines-1,0,message);
! 466: draw(scr);
! 467: wait_for(' ');
! 468: }
! 469:
! 470:
! 471: /*
! 472: * restscr:
! 473: * Restores the screen to the terminal
! 474: */
! 475: void
! 476: restscr(WINDOW *scr)
! 477: {
! 478: clearok(scr,TRUE);
! 479: touchwin(scr);
! 480: }
! 481:
! 482: /*
! 483: * netread:
! 484: * Read a byte, short, or long machine independently
! 485: * Always returns the value as an unsigned long.
! 486: */
! 487:
! 488: unsigned long
! 489: netread(int *error, int size, FILE *stream)
! 490: {
! 491: unsigned long result = 0L, /* What we read in */
! 492: partial; /* Partial value */
! 493: int nextc, /* The next byte */
! 494: i; /* To index through the result a byte at a time */
! 495:
! 496: /* Be sure we have a right sized chunk */
! 497: if (size < 1 || size > 4) {
! 498: *error = 1;
! 499: return(0L);
! 500: }
! 501:
! 502: for (i=0; i<size; i++) {
! 503: nextc = getc(stream);
! 504: if (nextc == EOF) {
! 505: *error = 1;
! 506: return(0L);
! 507: }
! 508: else {
! 509: partial = (unsigned long) (nextc & 0xff);
! 510: partial <<= 8*i;
! 511: result |= partial;
! 512: }
! 513: }
! 514:
! 515: *error = 0;
! 516: return(result);
! 517: }
! 518:
! 519:
! 520:
! 521: /*
! 522: * netwrite:
! 523: * Write out a byte, short, or long machine independently.
! 524: * value: What to write
! 525: * size: How much to write out
! 526: * stream: Where to write it
! 527: */
! 528:
! 529: int
! 530: netwrite(unsigned long value, int size, FILE *stream)
! 531: {
! 532: int i; /* Goes through value one byte at a time */
! 533: char outc; /* The next character to be written */
! 534:
! 535: /* Be sure we have a right sized chunk */
! 536: if (size < 1 || size > 4) return(0);
! 537:
! 538: for (i=0; i<size; i++) {
! 539: outc = (char) ((value >> (8 * i)) & 0xff);
! 540: putc(outc, stream);
! 541: }
! 542: return(size);
! 543: }
CVSweb