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