Mercurial > hg > early-roguelike
diff xrogue/io.c @ 133:e6179860cb76
Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 21 Apr 2015 08:55:20 -0400 |
parents | |
children | ce0cf824c192 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xrogue/io.c Tue Apr 21 08:55:20 2015 -0400 @@ -0,0 +1,563 @@ +/* + io.c - Various input/output functions + + XRogue: Expeditions into the Dungeons of Doom + Copyright (C) 1991 Robert Pietkivitch + All rights reserved. + + Based on "Advanced Rogue" + Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T + All rights reserved. + + Based on "Rogue: Exploring the Dungeons of Doom" + Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + All rights reserved. + + See the file LICENSE.TXT for full copyright and licensing information. +*/ + +#include <curses.h> +#include <ctype.h> +#include <stdarg.h> +#include "rogue.h" + +/* + * msg: + * Display a message at the top of the screen. + */ + +static char msgbuf[BUFSIZ]; +static int newpos = 0; + +/* VARARGS */ +void +msg(char *fmt, ...) +{ + va_list ap; + /* + * if the string is "", just clear the line + */ + if (*fmt == '\0') + { + wclear(msgw); + overwrite(cw, msgw); + wmove(msgw, 0, 0); + clearok(msgw, FALSE); + draw(msgw); + mpos = 0; + return; + } + /* + * otherwise add to the message and flush it out + */ + va_start(ap, fmt); + doadd(fmt, ap); + va_end(ap); + endmsg(); +} + +/* + * add things to the current message + */ + +/* VARARGS */ +void +addmsg(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + doadd(fmt, ap); + va_end(ap); +} + +/* + * If there is no current message, do nothing. Otherwise, prompt the + * player with the --More-- string. Then erase the message. + */ + +rmmsg() +{ + if (mpos) { + wclear(msgw); + overwrite(cw, msgw); + mvwaddstr(msgw, 0, 0, huh); + waddstr(msgw, morestr); + clearok(msgw, FALSE); + draw(msgw); + wait_for(' '); + msg(""); + } +} + +/* + * Display a new msg (giving him a chance to see the previous one if it + * is up there with the --More--) + */ + +endmsg() +{ + /* Needed to track where we are for 5.0 (PC) curses */ + register int x, y; + + if (mpos) { + /* + * If this message will fit on the line (plus space for --More--) + * then just add it (only during combat). + */ + if (player.t_quiet < 0 && mpos + newpos + strlen(morestr) + 5 < cols) { + wmove(msgw, 0, mpos + 5); + newpos += mpos + 5; + strcat(huh, " "); + } + else { + wclear(msgw); + overwrite(cw, msgw); + mvwaddstr(msgw, 0, 0, huh); + waddstr(msgw, morestr); + clearok(msgw, FALSE); + draw(msgw); + wait_for(' '); + wclear(msgw); + overwrite(cw, msgw); + wmove(msgw, 0, 0); + huh[0] = '\0'; + } + } + else { + wclear(msgw); + overwrite(cw, msgw); + wmove(msgw, 0, 0); + huh[0] = '\0'; + } + strcat(huh, msgbuf); + mvwaddstr(msgw, 0, 0, huh); + getyx(msgw, y, x); + mpos = newpos; + newpos = 0; + wmove(msgw, y, x); + clearok(msgw, FALSE); + draw(msgw); +} + +doadd(char *fmt, va_list ap) +{ + vsprintf((char *) &msgbuf[newpos], fmt, ap); + newpos = strlen(msgbuf); +} + +/* + * step_ok: + * returns true if it is ok for type to step on ch + * flgptr will be NULL if we don't know what the monster is yet! + */ + +step_ok(y, x, can_on_monst, flgptr) +register int y, x, can_on_monst; +register struct thing *flgptr; +{ + /* can_on_monst = MONSTOK if all we care about are physical obstacles */ + register struct linked_list *item; + register struct thing *tp; + unsigned char ch; + + /* What is here? Don't check monster window if MONSTOK is set */ + if (can_on_monst == MONSTOK) ch = mvinch(y, x); + else ch = winat(y, x); + + if (can_on_monst == FIGHTOK && isalpha(ch) && + (item = find_mons(y, x)) != NULL) { + tp = THINGPTR(item); /* What monster is here? */ + + /* We can hit it if we're after it */ + if (flgptr->t_dest == &tp->t_pos) return TRUE; + + /* + * Otherwise, if we're friendly we'll hit it unless it is also + * friendly or is our race. + */ + if (off(*flgptr, ISFRIENDLY) || + on(*tp, ISFRIENDLY) || + flgptr->t_index == tp->t_index) return FALSE; + else return TRUE; + } + else switch (ch) + { + case ' ': + case VERTWALL: + case HORZWALL: + case SECRETDOOR: + if (flgptr && on(*flgptr, CANINWALL)) return(TRUE); + return FALSE; + when SCROLL: + if (can_on_monst == MONSTOK) { /* Not a real obstacle */ + move_free = 0; /* check free movement */ + return(TRUE); + } + /* + * If it is a scroll, it might be a scare monster scroll + * so we need to look it up to see what type it is. + */ + if (flgptr && flgptr->t_ctype == C_MONSTER) { + move_free = 1; + item = find_obj(y, x); + if (item != NULL && + (OBJPTR(item))->o_which==S_SCARE && + (flgptr == NULL || flgptr->t_stats.s_intel < 17)) { + move_free = 2; + return(FALSE); /* All but smart ones are scared */ + } + } + return(TRUE); + otherwise: + return (!isalpha(ch)); + } + /* return(FALSE); */ + /*NOTREACHED*/ +} + +/* + * shoot_ok: + * returns true if it is ok for type to shoot over ch + */ + +shoot_ok(int ch) +{ + switch (ch) + { + case ' ': + case VERTWALL: + case HORZWALL: + case SECRETDOOR: + case FOREST: + return FALSE; + default: + return (!isalpha(ch)); + } +} + +/* + * status: + * Display the important stats line. Keep the cursor where it was. + */ + +status(display) +bool display; /* is TRUE, display unconditionally */ +{ + register struct stats *stat_ptr, *max_ptr; + register int oy = 0, ox = 0, temp; + register char *pb; + char buf[LINELEN]; + static int hpwidth = 0, s_hungry = -1; + static int s_lvl = -1, s_hp = -1, s_str, maxs_str, + s_ac = 0; + static short s_intel, s_dext, s_wisdom, s_const, s_charisma; + static short maxs_intel, maxs_dext, maxs_wisdom, maxs_const, maxs_charisma; + static unsigned long s_exp = 0; + static int s_carry, s_pack; + bool first_line=FALSE; + + /* Go to English mode */ + nofont(cw); + + stat_ptr = &pstats; + max_ptr = &max_stats; + + /* + * If nothing has changed in the first line, then skip it + */ + if (!display && + s_lvl == level && + s_intel == stat_ptr->s_intel && + s_wisdom == stat_ptr->s_wisdom && + s_dext == dex_compute() && + s_const == stat_ptr->s_const && + s_charisma == stat_ptr->s_charisma && + s_str == str_compute() && + s_hungry == hungry_state && + maxs_intel == max_ptr->s_intel && + maxs_wisdom == max_ptr->s_wisdom && + maxs_dext == max_ptr->s_dext && + maxs_const == max_ptr->s_const && + maxs_charisma == max_ptr->s_charisma && + maxs_str == max_ptr->s_str ) goto line_two; + + /* Display the first line */ + first_line = TRUE; + getyx(cw, oy, ox); + sprintf(buf, "Int:%d(%d) Str:%d", stat_ptr->s_intel, + max_ptr->s_intel, str_compute()); + + /* Maximum strength */ + pb = &buf[strlen(buf)]; + sprintf(pb, "(%d)", max_ptr->s_str); + + pb = &buf[strlen(buf)]; + sprintf(pb, " Wis:%d(%d) Dxt:%d(%d) Con:%d(%d) Cha:%d(%d)", + stat_ptr->s_wisdom,max_ptr->s_wisdom,dex_compute(),max_ptr->s_dext, + stat_ptr->s_const,max_ptr->s_const,stat_ptr->s_charisma, + max_ptr->s_charisma); + + /* Update first line status */ + s_intel = stat_ptr->s_intel; + s_wisdom = stat_ptr->s_wisdom; + s_dext = dex_compute(); + s_const = stat_ptr->s_const; + s_charisma = stat_ptr->s_charisma; + s_str = str_compute(); + maxs_intel = max_ptr->s_intel; + maxs_wisdom = max_ptr->s_wisdom; + maxs_dext = max_ptr->s_dext; + maxs_const = max_ptr->s_const; + maxs_charisma = max_ptr->s_charisma; + maxs_str = max_ptr->s_str; + + /* Print the line */ + mvwaddstr(cw, lines-2, 0, buf); + switch (hungry_state) { + case F_SATIATED: + waddstr(cw, " Satiated"); + when F_OKAY: ; + when F_HUNGRY: + waddstr(cw, " Hungry"); + when F_WEAK: + waddstr(cw, " Weak"); + when F_FAINT: + waddstr(cw, " Fainting"); + } + wclrtoeol(cw); + s_hungry = hungry_state; + + /* + * If nothing has changed since the last status, don't + * bother. + */ +line_two: + if (!display && + s_lvl == level && + s_hp == stat_ptr->s_hpt && + s_ac == ac_compute(FALSE) - dext_prot(s_dext) && + s_pack == stat_ptr->s_pack && + s_carry == stat_ptr->s_carry && + s_exp == stat_ptr->s_exp ) { + newfont(cw); + return; + } + + if (!first_line) getyx(cw, oy, ox); + if (s_hp != max_ptr->s_hpt) { + temp = s_hp = max_ptr->s_hpt; + for (hpwidth = 0; temp; hpwidth++) + temp /= 10; + } + sprintf(buf, "Lvl:%d Hp:%*d(%*d) Ac:%d Carry:%d(%d) Exp:%d/%lu %s", + level, hpwidth, stat_ptr->s_hpt, hpwidth, max_ptr->s_hpt, + ac_compute(FALSE) - dext_prot(s_dext),stat_ptr->s_pack/10, + stat_ptr->s_carry/10, stat_ptr->s_lvl, stat_ptr->s_exp, + cnames[player.t_ctype][min(stat_ptr->s_lvl-1, NUM_CNAMES-1)]); + + /* + * Save old status + */ + s_lvl = level; + s_hp = stat_ptr->s_hpt; + s_ac = ac_compute(FALSE) - dext_prot(s_dext); + s_pack = stat_ptr->s_pack; + s_carry = stat_ptr->s_carry; + s_exp = stat_ptr->s_exp; + mvwaddstr(cw, lines-1, 0, buf); + wclrtoeol(cw); + newfont(cw); + wmove(cw, oy, ox); +} + +/* + * wait_for + * Sit around until the guy types the right key + */ + +wait_for(ch) +register char ch; +{ + register char c; + + clearok(msgw, FALSE); + if (ch == '\n') { + while ((c = wgetch(msgw)) != '\n' && c != '\r') { + continue; + } + } + else { + while (wgetch(msgw) != ch) { + continue; + } + } +} + + +/* + * over_win: + * Given a current window, a new window, and the max y and x of the + * new window, paint the new window on top of the old window without + * destroying any of the old window. Current window and new window + * are assumed to have lines lines and cols columns (max y and max x + * pertain only the the useful information to be displayed. + * If redraw is non-zero, we wait for the character "redraw" to be + * typed and then redraw the starting screen. + */ + +over_win(oldwin, newin, maxy, maxx, cursory, cursorx, redraw) +WINDOW *oldwin, *newin; +int maxy, maxx, cursory, cursorx; +char redraw; +{ + char blanks[LINELEN+1]; + register int line, i; + WINDOW *ow; /* Overlay window */ + + /* Create a blanking line */ + for (i=0; i<maxx && i<cols && i<LINELEN; i++) blanks[i] = ' '; + blanks[i] = '\0'; + + /* Create the window we will display */ + ow = newwin(lines, cols, 0, 0); + + /* Blank out the area we want to use */ + if (oldwin == cw) { + msg(""); + line = 1; + } + else line = 0; + + overwrite(oldwin, ow); /* Get a copy of the old window */ + + /* Do the remaining blanking */ + for (; line < maxy; line++) mvwaddstr(ow, line, 0, blanks); + + overlay(newin, ow); /* Overlay our new window */ + + /* Move the cursor to the specified location */ + wmove(ow, cursory, cursorx); + + clearok(ow, FALSE); /* Draw inventory without clearing */ + draw(ow); + + if (redraw) { + wait_for(redraw); + + clearok(oldwin, FALSE); /* Setup to redraw current screen */ + touchwin(oldwin); /* clearing first */ + draw(oldwin); + } + + delwin(ow); +} + + +/* + * show_win: + * function used to display a window and wait before returning + */ + +show_win(scr, message) +register WINDOW *scr; +char *message; +{ + mvwaddstr(scr, 0, 0, message); + touchwin(scr); + wmove(scr, hero.y, hero.x); + draw(scr); + wait_for(' '); + restscr(cw); +} + +/* + * dbotline: + * Displays message on bottom line and waits for a space to return + */ + +dbotline(scr,message) +WINDOW *scr; +char *message; +{ + mvwaddstr(scr,lines-1,0,message); + draw(scr); + wait_for(' '); +} + +/* + * restscr: + * Restores the screen to the terminal + */ + +restscr(scr) +WINDOW *scr; +{ + clearok(scr,TRUE); + touchwin(scr); + draw(scr); +} + +/* + * netread: + * Read a byte, short, or long machine independently + * Always returns the value as an unsigned long. + */ + +unsigned long +netread(error, size, stream) +int *error; +int size; +FILE *stream; +{ + unsigned long result = 0L, /* What we read in */ + partial; /* Partial value */ + int nextc, /* The next byte */ + i; /* To index through the result a byte at a time */ + + /* Be sure we have a right sized chunk */ + if (size < 1 || size > 4) { + *error = 1; + return(0L); + } + + for (i=0; i<size; i++) { + nextc = getc(stream); + if (nextc == EOF) { + *error = 1; + return(0L); + } + else { + partial = (unsigned long) (nextc & 0xff); + partial <<= 8*i; + result |= partial; + } + } + + *error = 0; + return(result); +} + +/* + * netwrite: + * Write out a byte, short, or long machine independently. + */ + +netwrite(value, size, stream) +unsigned long value; /* What to write */ +int size; /* How much to write out */ +FILE *stream; /* Where to write it */ +{ + int i; /* Goes through value one byte at a time */ + char outc; /* The next character to be written */ + + /* Be sure we have a right sized chunk */ + if (size < 1 || size > 4) return(0); + + for (i=0; i<size; i++) { + outc = (char) ((value >> (8 * i)) & 0xff); + putc(outc, stream); + } + return(size); +} +