diff arogue7/io.c @ 125:adfa37e67084

Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Fri, 08 May 2015 15:24:40 -0400
parents
children b786053d2f37
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/io.c	Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,539 @@
+/*
+ * io.c  -  Various input/output functions
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985, 1986 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.
+ */
+
+/*
+ * Various input/output functions
+ */
+
+#include "curses.h"
+#include <stdarg.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * msg:
+ *	Display a message at the top of the screen.
+ */
+
+static char msgbuf[BUFSIZ];
+static int newpos = 0;
+
+/*VARARGS1*/
+msg(char *fmt, ...)
+{
+    va_list ap;
+    /*
+     * if the string is "", just clear the line
+     */
+    if (*fmt == '\0')
+    {
+	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
+ */
+addmsg(char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    doadd(fmt, ap);
+    va_end(ap);
+}
+
+/*
+ * 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;
+
+    strcpy(huh, msgbuf);
+    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) + 2 < cols) {
+	    wmove(msgw, 0, mpos + 2);
+	    newpos += mpos + 2;
+	}
+	else {
+	    wmove(msgw, 0, mpos);
+	    waddstr(msgw, morestr);
+	    draw(cw);
+	    draw(msgw);
+	    wait_for(' ');
+	    overwrite(cw,msgw);
+	    wmove(msgw, 0, 0);
+	    touchwin(cw);
+	}
+    }
+    else {
+	overwrite(cw,msgw);
+        wmove(msgw, 0, 0);
+    }
+    waddstr(msgw, msgbuf);
+    getyx(msgw, y, x);
+    mpos = newpos;
+    newpos = 0;
+    wmove(msgw, y, x);
+    draw(cw);
+    clearok(msgw, FALSE);
+    draw(msgw);
+}
+
+doadd(char *fmt, va_list ap)
+{
+
+    /*
+     * Do the printf into buf
+     */
+    vsprintf(&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;
+    char ch;
+
+    /* What is here?  Don't check monster window if MONSTOK is set */
+    if (can_on_monst == MONSTOK) ch = CCHAR( mvinch(y, x) );
+    else ch = CCHAR( 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 '|':
+	case '-':
+	case SECRETDOOR:
+	    if (flgptr && on(*flgptr, CANINWALL)) return(TRUE);
+	    return FALSE;
+	when SCROLL:
+	    if (can_on_monst == MONSTOK) return(TRUE); /* Not a real obstacle */
+	    /*
+	     * 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) {
+		item = find_obj(y, x);
+		if (item != NULL &&
+		    (OBJPTR(item))->o_which==S_SCARE &&
+		    (flgptr == NULL || flgptr->t_stats.s_intel < 16))
+			return(FALSE); /* All but smart ones are scared */
+	    }
+	    return(TRUE);
+	otherwise:
+	    return (!isalpha(ch));
+    }
+    return(FALSE);
+}
+/*
+ * shoot_ok:
+ *	returns true if it is ok for type to shoot over ch
+ */
+
+shoot_ok(ch)
+{
+    switch (ch)
+    {
+	case ' ':
+	case '|':
+	case '-':
+	case SECRETDOOR:
+	case FOREST:
+	    return FALSE;
+	default:
+	    return (!isalpha(ch));
+    }
+}
+
+/*
+ * readchar:
+ *	flushes stdout so that screen is up to date and then returns
+ *	getchar.
+ */
+
+readchar()
+{
+    int ch;
+
+    ch = md_readchar(cw);
+
+    if ((ch == 3) || (ch == 0))
+    {
+        quit(0);
+        return(27);
+    }
+
+    return(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, ox, temp;
+    register char *pb;
+    static 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;
+
+    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			) 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);
+    wmove(cw, oy, ox);
+}
+
+/*
+ * wait_for
+ *	Sit around until the guy types the right key
+ */
+wait_for(ch)
+register char ch;
+{
+    register char c;
+
+    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;
+{
+    static 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(' ');
+    clearok(cw, TRUE);
+    touchwin(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);
+}
+
+/*
+ * 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);
+}