diff arogue5/options.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 c56f672244f4
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/options.c	Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,469 @@
+/*
+ * This file has all the code for the option command.
+ * I would rather this command were not necessary, but
+ * it is the only way to keep the wolves off of my back.
+ *
+ * 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 "rogue.h"
+
+#define	NUM_OPTS	(sizeof optlist / sizeof (OPTION))
+
+
+/*
+ * description of an option and what to do with it
+ */
+struct optstruct {
+    char	*o_name;	/* option name */
+    char	*o_prompt;	/* prompt for interactive entry */
+    int 	*o_opt;		/* pointer to thing to set */
+    int		(*o_putfunc)();	/* function to print value */
+    int		(*o_getfunc)();	/* function to get value interactively */
+};
+
+typedef struct optstruct	OPTION;
+
+int	put_bool(), 
+	get_bool(),
+	put_str(),
+	get_str(),
+	put_abil(),
+	get_abil(),
+	get_quest(),
+	put_quest();
+
+OPTION	optlist[] = {
+    {"terse",	 "Terse output: ",
+		 (int *) &terse,	put_bool,	get_bool	},
+    {"flush",	 "Flush typeahead during battle: ",
+		 (int *) &fight_flush,	put_bool,	get_bool	},
+    {"jump",	 "Show position only at end of run: ",
+		 (int *) &jump,		put_bool,	get_bool	},
+    {"step",	"Do inventories one line at a time: ",
+		(int *) &slow_invent,	put_bool,	get_bool	},
+    {"askme",	"Ask me about unidentified things: ",
+		(int *) &askme,		put_bool,	get_bool	},
+    {"pickup", "Pick things up automatically: ",
+		(int *) &auto_pickup,	put_bool,	get_bool	},
+    {"name",	 "Name: ",
+		(int *) whoami,		put_str,	get_str		},
+    {"fruit",	 "Fruit: ",
+		(int *) fruit,		put_str,	get_str		},
+    {"file",	 "Save file: ",
+		(int *) file_name,	put_str,	get_str		},
+    {"score",	 "Score file: ",
+		(int *) score_file,	put_str,	get_str		},
+    {"class",	"Character class: ",
+		(int *)&char_type,	put_abil,	get_abil	},
+    {"quest",	"Quest item: ",
+		(int *) &quest_item,	put_quest,	get_quest	}
+};
+
+/*
+ * The ability field is read-only
+ */
+get_abil(abil, win)
+int *abil;
+WINDOW *win;
+{
+    register int oy, ox;
+
+    getyx(win, oy, ox);
+    put_abil(abil, win);
+    get_ro(win, oy, ox);
+}
+
+/*
+ * The quest field is read-only
+ */
+get_quest(quest, win)
+int *quest;
+WINDOW *win;
+{
+    register int oy, ox;
+
+    getyx(win, oy, ox);
+    waddstr(win, rel_magic[*quest].mi_name);
+    get_ro(win, oy, ox);
+}
+
+/*
+ * get_ro:
+ *	"Get" a read-only value.
+ */
+
+get_ro(win, oy, ox)
+WINDOW *win;
+register int oy, ox;
+{
+    register int ny, nx;
+    register bool op_bad;
+    
+    op_bad = TRUE;
+    getyx(win, ny, nx);
+    while(op_bad)	
+    {
+	wmove(win, oy, ox);
+	draw(win);
+	switch (wgetch(win))
+	{
+	    case '\n':
+	    case '\r':
+		op_bad = FALSE;
+		break;
+	    case '\033':
+	    case '\007':
+		return QUIT;
+	    case '-':
+		return MINUS;
+	    default:
+		mvwaddstr(win, ny, nx + 5, "(no change allowed)");
+	}
+    }
+    wmove(win, ny, nx + 5);
+    wclrtoeol(win);
+    wmove(win, ny, nx);
+    waddch(win, '\n');
+    return NORM;
+}
+
+/*
+ * allow changing a boolean option and print it out
+ */
+
+get_bool(bp, win)
+bool *bp;
+WINDOW *win;
+{
+    register int oy, ox;
+    register bool op_bad;
+
+    op_bad = TRUE;
+    getyx(win, oy, ox);
+    waddstr(win, *bp ? "True" : "False");
+    while(op_bad)	
+    {
+	wmove(win, oy, ox);
+	draw(win);
+	switch (wgetch(win))
+	{
+	    case 't':
+	    case 'T':
+		*bp = TRUE;
+		op_bad = FALSE;
+		break;
+	    case 'f':
+	    case 'F':
+		*bp = FALSE;
+		op_bad = FALSE;
+		break;
+	    case '\n':
+	    case '\r':
+		op_bad = FALSE;
+		break;
+	    case '\033':
+	    case '\007':
+		return QUIT;
+	    case '-':
+		return MINUS;
+	    default:
+		mvwaddstr(win, oy, ox + 10, "(T or F)");
+	}
+    }
+    wmove(win, oy, ox);
+    wclrtoeol(win);
+    waddstr(win, *bp ? "True" : "False");
+    waddch(win, '\n');
+    return NORM;
+}
+
+
+/*
+ * set a string option
+ */
+get_str(opt, win)
+register char *opt;
+WINDOW *win;
+{
+    register char *sp;
+    register int c, oy, ox;
+    char buf[LINELEN];
+
+    draw(win);
+    getyx(win, oy, ox);
+    /*
+     * loop reading in the string, and put it in a temporary buffer
+     */
+    for (sp = buf;
+	(c = wgetch(win)) != '\n'	&& 
+	c != '\r'			&& 
+	c != '\033'			&& 
+	c != '\007'			&&
+	sp < &buf[LINELEN-1];
+	wclrtoeol(win), draw(win))
+    {
+	if (c == -1)
+	    continue;
+	else if (c == md_erasechar()) /* process erase character */
+	{
+	    if (sp > buf)
+	    {
+		register int i;
+
+		sp--;
+		for (i = strlen(unctrl(*sp)); i; i--)
+		    waddch(win, '\b');
+	    }
+	    continue;
+	}
+	else if (c == md_killchar()) /* process kill character */
+	{
+	    sp = buf;
+	    wmove(win, oy, ox);
+	    continue;
+	}
+	else if (sp == buf)
+	    if (c == '-' && win == hw)	/* To move back a line in hw */
+		break;
+	    else if (c == '~')
+	    {
+		strcpy(buf, home);
+		waddstr(win, home);
+		sp += strlen(home);
+		continue;
+	    }
+	*sp++ = c;
+	waddstr(win, unctrl(c));
+    }
+    *sp = '\0';
+    if (sp > buf)	/* only change option if something has been typed */
+	strucpy(opt, buf, strlen(buf));
+    wmove(win, oy, ox);
+    waddstr(win, opt);
+    waddch(win, '\n');
+    draw(win);
+    if (win == cw)
+	mpos += (int)(sp - buf);
+    if (c == '-')
+	return MINUS;
+    else if (c == '\033' || c == '\007')
+	return QUIT;
+    else
+	return NORM;
+}
+
+
+
+/*
+ * print and then set options from the terminal
+ */
+option()
+{
+    register OPTION	*op;
+    register int	retval;
+
+    wclear(hw);
+    touchwin(hw);
+    /*
+     * Display current values of options
+     */
+    for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
+    {
+	waddstr(hw, op->o_prompt);
+	(*op->o_putfunc)(op->o_opt, hw);
+	waddch(hw, '\n');
+    }
+    /*
+     * Set values
+     */
+    wmove(hw, 0, 0);
+    for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
+    {
+	waddstr(hw, op->o_prompt);
+	if ((retval = (*op->o_getfunc)(op->o_opt, hw)))
+	    if (retval == QUIT)
+		break;
+	    else if (op > optlist) {	/* MINUS */
+		wmove(hw, (int)(op - optlist) - 1, 0);
+		op -= 2;
+	    }
+	    else	/* trying to back up beyond the top */
+	    {
+		putchar('\007');
+		wmove(hw, 0, 0);
+		op--;
+	    }
+    }
+    /*
+     * Switch back to original screen
+     */
+    mvwaddstr(hw, LINES-1, 0, spacemsg);
+    draw(hw);
+    wait_for(hw,' ');
+    clearok(cw, TRUE);
+    touchwin(cw);
+    after = FALSE;
+}
+
+/*
+ * parse options from string, usually taken from the environment.
+ * the string is a series of comma seperated values, with booleans
+ * being stated as "name" (true) or "noname" (false), and strings
+ * being "name=....", with the string being defined up to a comma
+ * or the end of the entire option string.
+ */
+
+parse_opts(str)
+register char *str;
+{
+    register char *sp;
+    register OPTION *op;
+    register int len;
+
+    while (*str)
+    {
+	/*
+	 * Get option name
+	 */
+	for (sp = str; isalpha(*sp); sp++)
+	    continue;
+	len = (int)(sp - str);
+	/*
+	 * Look it up and deal with it
+	 */
+	for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
+	    if (EQSTR(str, op->o_name, len))
+	    {
+		if (op->o_putfunc == put_bool)	/* if option is a boolean */
+		    *(bool *)op->o_opt = TRUE;
+		else				/* string option */
+		{
+		    register char *start;
+		    char value[80];
+
+		    /*
+		     * Skip to start of string value
+		     */
+		    for (str = sp + 1; *str == '='; str++)
+			continue;
+		    if (*str == '~')
+		    {
+			strcpy((char *) value, home);
+			start = (char *) value + strlen(home);
+			while (*++str == '/')
+			    continue;
+		    }
+		    else
+			start = (char *) value;
+		    /*
+		     * Skip to end of string value
+		     */
+		    for (sp = str + 1; *sp && *sp != ','; sp++)
+			continue;
+		    strucpy(start, str, sp - str);
+
+		    /* Put the value into the option field */
+		    if (op->o_putfunc != put_abil) 
+			strcpy((char *)op->o_opt, value);
+
+		    else if (*op->o_opt == -1) { /* Only init ability once */
+			register int len = strlen(value);
+
+			if (isupper(value[0])) value[0] = tolower(value[0]);
+			if (EQSTR(value, "fighter", len))
+				*op->o_opt = C_FIGHTER;
+			else if (EQSTR(value, "magic", min(len, 5)))
+				*op->o_opt = C_MAGICIAN;
+			else if (EQSTR(value, "cleric", len))
+				*op->o_opt = C_CLERIC;
+			else if (EQSTR(value, "thief", len))
+				*op->o_opt = C_THIEF;
+		    }
+		}
+		break;
+	    }
+	    /*
+	     * check for "noname" for booleans
+	     */
+	    else if (op->o_putfunc == put_bool
+	      && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
+	    {
+		*(bool *)op->o_opt = FALSE;
+		break;
+	    }
+
+	/*
+	 * skip to start of next option name
+	 */
+	while (*sp && !isalpha(*sp))
+	    sp++;
+	str = sp;
+    }
+}
+
+
+/*
+ * print the character type
+ */
+put_abil(ability, win)
+int *ability;
+WINDOW *win;
+{
+    char *abil;
+
+    switch (*ability) {
+	case C_MAGICIAN:abil = "Magic User";
+	when C_FIGHTER:	abil = "Fighter";
+	when C_CLERIC:	abil = "Cleric";
+	when C_THIEF:	abil = "Thief";
+	otherwise:	abil = "??";
+    }
+    waddstr(win, abil);
+}
+
+
+/*
+ * print out the quest
+ */
+
+put_quest(quest, win)
+int *quest;
+WINDOW *win;
+{
+    waddstr(win, rel_magic[*quest].mi_name);
+}
+
+
+/*
+ * put out a boolean
+ */
+put_bool(b, win)
+bool	*b;
+WINDOW *win;
+{
+    waddstr(win, *b ? "True" : "False");
+}
+
+
+
+
+/*
+ * put out a string
+ */
+put_str(str, win)
+char *str;
+WINDOW *win;
+{
+    waddstr(win, str);
+}