diff arogue5/io.c @ 63:0ed67132cf10

Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 09 Aug 2012 22:58:48 +0000
parents
children c49f7927b0fa
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/io.c	Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,489 @@
+/*
+ * Various input/output functions
+ *
+ * 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;
+
+/*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()
+{
+    strncpy(huh, msgbuf, sizeof(huh));
+
+    huh[ sizeof(huh) - 1 ] = 0;
+
+    if (mpos)
+    {
+	wmove(msgw, 0, mpos);
+	waddstr(msgw, morestr);
+	draw(cw);
+	draw(msgw);
+	wait_for(msgw,' ');
+	overwrite(cw,msgw);
+	wmove(msgw,0,0);
+	touchwin(cw);
+    }
+    else {
+	overwrite(cw,msgw);
+	wmove(msgw,0,0);
+    }
+    waddstr(msgw, msgbuf);
+    mpos = newpos;
+    newpos = 0;
+    msgbuf[0] = '\0';
+    draw(cw);
+    clearok(msgw, FALSE);
+    draw(msgw);
+}
+
+doadd(char *fmt, va_list ap)
+{
+    /*
+     * Do the sprintf into newmsg and append to msgbuf
+     */
+
+    vsnprintf(&msgbuf[newpos], sizeof(msgbuf)-newpos-1, 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;
+    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) );
+
+    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));
+    }
+}
+/*
+ * 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 = 0, ox = 0, temp;
+    register char *pb;
+    static char buf[LINELEN];
+    static int hpwidth = 0, s_hungry = -1;
+    static int s_lvl = -1, s_pur, 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;
+
+    /* Use a mini status version if we have a small window */
+    if (COLS < 80) {
+	ministat();
+	return;
+    }
+
+    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_pack == stat_ptr->s_pack		&&
+	s_carry == stat_ptr->s_carry		&&
+	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)  Const:%d(%d)  Carry:%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_pack/10,
+	stat_ptr->s_carry/10);
+
+    /* 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();
+    s_pack = stat_ptr->s_pack;
+    s_carry = stat_ptr->s_carry;
+    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);
+    wclrtoeol(cw);
+
+    /*
+     * If nothing has changed since the last status, don't
+     * bother.
+     */
+line_two: 
+    if (!display					&&
+	s_hp == stat_ptr->s_hpt				&& 
+	s_exp == stat_ptr->s_exp			&& 
+        s_pur == purse					&& 
+	s_ac == ac_compute() - dext_prot(s_dext)	&&
+	s_lvl == level 					&& 
+	s_hungry == hungry_state			) 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  Au:%d  Hp:%*d(%*d)  Ac:%d  Exp:%d/%lu  %s",
+	level, purse, hpwidth, stat_ptr->s_hpt, hpwidth, max_ptr->s_hpt,
+	ac_compute() - dext_prot(s_dext),stat_ptr->s_lvl, stat_ptr->s_exp, 
+	cnames[player.t_ctype][min(stat_ptr->s_lvl-1, 10)]);
+
+    /*
+     * Save old status
+     */
+    s_lvl = level;
+    s_pur = purse;
+    s_hp = stat_ptr->s_hpt;
+    s_exp = stat_ptr->s_exp; 
+    s_ac = ac_compute() - dext_prot(s_dext);
+    mvwaddstr(cw, LINES - 1, 0, buf);
+    switch (hungry_state)
+    {
+	case 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;
+    wmove(cw, oy, ox);
+}
+
+ministat()
+{
+    register int oy, ox, temp;
+    static char buf[LINELEN];
+    static int hpwidth = 0;
+    static int s_lvl = -1, s_pur, s_hp = -1;
+
+    /*
+     * If nothing has changed since the last status, don't
+     * bother.
+     */
+    if (s_hp == pstats.s_hpt && s_pur == purse && s_lvl == level)
+	    return;
+	
+    getyx(cw, oy, ox);
+    if (s_hp != max_stats.s_hpt)
+    {
+	temp = s_hp = max_stats.s_hpt;
+	for (hpwidth = 0; temp; hpwidth++)
+	    temp /= 10;
+    }
+    sprintf(buf, "Lv: %d  Au: %-5d  Hp: %*d(%*d)",
+	level, purse, hpwidth, pstats.s_hpt, hpwidth, max_stats.s_hpt);
+
+    /*
+     * Save old status
+     */
+    s_lvl = level;
+    s_pur = purse;
+    s_hp = pstats.s_hpt;
+    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(win,ch)
+WINDOW *win;
+register char ch;
+{
+    register char c;
+
+    if (ch == '\n')
+        while ((c = wgetch(win)) != '\n' && c != '\r')
+	    continue;
+    else
+        while (wgetch(win) != ch)
+	    continue;
+}
+
+/*
+ * 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(scr,' ');
+    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(scr,' ');	
+}
+
+
+/*
+ * 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);
+}