134599Sbostic /*
234599Sbostic * io.c - input/output routines for Phantasia
334599Sbostic */
434599Sbostic
534599Sbostic #include "include.h"
634599Sbostic
734599Sbostic /************************************************************************
834599Sbostic /
934599Sbostic / FUNCTION NAME: getstring()
1034599Sbostic /
1134599Sbostic / FUNCTION: read a string from operator
1234599Sbostic /
1334599Sbostic / AUTHOR: E. A. Estes, 12/4/85
1434599Sbostic /
1534599Sbostic / ARGUMENTS:
1634599Sbostic / char *cp - pointer to buffer area to fill
1734599Sbostic / int mx - maximum number of characters to put in buffer
1834599Sbostic /
1934599Sbostic / RETURN VALUE: none
2034599Sbostic /
2134599Sbostic / MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
2234599Sbostic / wclrtoeol()
2334599Sbostic /
2434599Sbostic / GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
2534599Sbostic /
2634599Sbostic / GLOBAL OUTPUTS: _iob[]
2734599Sbostic /
2834599Sbostic / DESCRIPTION:
2934599Sbostic / Read a string from the keyboard.
3034599Sbostic / This routine is specially designed to:
3134599Sbostic /
3234599Sbostic / - strip non-printing characters (unless Wizard)
3334599Sbostic / - echo, if desired
3434599Sbostic / - redraw the screen if CH_REDRAW is entered
3534599Sbostic / - read in only 'mx - 1' characters or less characters
3634599Sbostic / - nul-terminate string, and throw away newline
3734599Sbostic /
3834599Sbostic / 'mx' is assumed to be at least 2.
3934599Sbostic /
4034599Sbostic /************************************************************************/
4134599Sbostic
getstring(cp,mx)4234599Sbostic getstring(cp, mx)
4334599Sbostic register char *cp;
4434599Sbostic register int mx;
4534599Sbostic {
4634599Sbostic register char *inptr; /* pointer into string for next string */
4734599Sbostic int x, y; /* original x, y coordinates on screen */
4834599Sbostic int ch; /* input */
4934599Sbostic
5034599Sbostic getyx(stdscr, y, x); /* get coordinates on screen */
5134599Sbostic inptr = cp;
5234599Sbostic *inptr = '\0'; /* clear string to start */
5334599Sbostic --mx; /* reserve room in string for nul terminator */
5434599Sbostic
5534599Sbostic do
5634599Sbostic /* get characters and process */
5734599Sbostic {
5834599Sbostic if (Echo)
5934599Sbostic mvaddstr(y, x, cp); /* print string on screen */
6034599Sbostic clrtoeol(); /* clear any data after string */
6134599Sbostic refresh(); /* update screen */
6234599Sbostic
6334599Sbostic ch = getchar(); /* get character */
6434599Sbostic
6534599Sbostic switch (ch)
6634599Sbostic {
6734599Sbostic case CH_ERASE: /* back up one character */
6834599Sbostic if (inptr > cp)
6934599Sbostic --inptr;
7034599Sbostic break;
7134599Sbostic
7234599Sbostic case CH_KILL: /* back up to original location */
7334599Sbostic inptr = cp;
7434599Sbostic break;
7534599Sbostic
7634599Sbostic case CH_NEWLINE: /* terminate string */
7734599Sbostic break;
7834599Sbostic
7934599Sbostic case CH_REDRAW: /* redraw screen */
8034599Sbostic clearok(stdscr, TRUE);
8134599Sbostic continue;
8234599Sbostic
8334599Sbostic default: /* put data in string */
8434599Sbostic if (ch >= ' ' || Wizard)
8534599Sbostic /* printing char; put in string */
8634599Sbostic *inptr++ = ch;
8734599Sbostic }
8834599Sbostic
8934599Sbostic *inptr = '\0'; /* terminate string */
9034599Sbostic }
9134599Sbostic while (ch != CH_NEWLINE && inptr < cp + mx);
9234599Sbostic }
9334599Sbostic /**/
9434599Sbostic /************************************************************************
9534599Sbostic /
9634599Sbostic / FUNCTION NAME: more()
9734599Sbostic /
9834599Sbostic / FUNCTION: pause and prompt player
9934599Sbostic /
10034599Sbostic / AUTHOR: E. A. Estes, 12/4/85
10134599Sbostic /
10234599Sbostic / ARGUMENTS:
10334599Sbostic / int where - line on screen on which to pause
10434599Sbostic /
10534599Sbostic / RETURN VALUE: none
10634599Sbostic /
10734599Sbostic / MODULES CALLED: wmove(), waddstr(), getanswer()
10834599Sbostic /
10934599Sbostic / GLOBAL INPUTS: *stdscr
11034599Sbostic /
11134599Sbostic / GLOBAL OUTPUTS: none
11234599Sbostic /
11334599Sbostic / DESCRIPTION:
11434599Sbostic / Print a message, and wait for a space character.
11534599Sbostic /
11634599Sbostic /************************************************************************/
11734599Sbostic
more(where)11834599Sbostic more(where)
11934599Sbostic int where;
12034599Sbostic {
12134599Sbostic mvaddstr(where, 0, "-- more --");
12234599Sbostic getanswer(" ", FALSE);
12334599Sbostic }
12434599Sbostic /**/
12534599Sbostic /************************************************************************
12634599Sbostic /
12734599Sbostic / FUNCTION NAME: infloat()
12834599Sbostic /
12934599Sbostic / FUNCTION: input a floating point number from operator
13034599Sbostic /
13134599Sbostic / AUTHOR: E. A. Estes, 12/4/85
13234599Sbostic /
13334599Sbostic / ARGUMENTS: none
13434599Sbostic /
13534599Sbostic / RETURN VALUE: floating point number from operator
13634599Sbostic /
13734599Sbostic / MODULES CALLED: sscanf(), getstring()
13834599Sbostic /
13934599Sbostic / GLOBAL INPUTS: Databuf[]
14034599Sbostic /
14134599Sbostic / GLOBAL OUTPUTS: none
14234599Sbostic /
14334599Sbostic / DESCRIPTION:
14434599Sbostic / Read a string from player, and scan for a floating point
14534599Sbostic / number.
14634599Sbostic / If no valid number is found, return 0.0.
14734599Sbostic /
14834599Sbostic /************************************************************************/
14934599Sbostic
15034599Sbostic double
infloat()15134599Sbostic infloat()
15234599Sbostic {
15334599Sbostic double result; /* return value */
15434599Sbostic
15534599Sbostic getstring(Databuf, SZ_DATABUF);
15634613Sbostic if (sscanf(Databuf, "%lf", &result) < 1)
15734599Sbostic /* no valid number entered */
15834599Sbostic result = 0.0;
15934599Sbostic
16034599Sbostic return(result);
16134599Sbostic }
16234599Sbostic /**/
16334599Sbostic /************************************************************************
16434599Sbostic /
16534599Sbostic / FUNCTION NAME: inputoption()
16634599Sbostic /
16734599Sbostic / FUNCTION: input an option value from player
16834599Sbostic /
16934599Sbostic / AUTHOR: E. A. Estes, 12/4/85
17034599Sbostic /
17134599Sbostic / ARGUMENTS: none
17234599Sbostic /
17334599Sbostic / RETURN VALUE: none
17434599Sbostic /
17534599Sbostic / MODULES CALLED: floor(), drandom(), getanswer()
17634599Sbostic /
17734599Sbostic / GLOBAL INPUTS: Player
17834599Sbostic /
17934599Sbostic / GLOBAL OUTPUTS: Player
18034599Sbostic /
18134599Sbostic / DESCRIPTION:
18234599Sbostic / Age increases with every move.
18334599Sbostic / Refresh screen, and get a single character option from player.
18434599Sbostic / Return a random value if player's ring has gone bad.
18534599Sbostic /
18634599Sbostic /************************************************************************/
18734599Sbostic
inputoption()18834599Sbostic inputoption()
18934599Sbostic {
19034599Sbostic ++Player.p_age; /* increase age */
19134599Sbostic
19234599Sbostic if (Player.p_ring.ring_type != R_SPOILED)
19334599Sbostic /* ring ok */
19434599Sbostic return(getanswer("T ", TRUE));
19534599Sbostic else
19634599Sbostic /* bad ring */
19734599Sbostic {
19834599Sbostic getanswer(" ", TRUE);
19934599Sbostic return((int) ROLL(0.0, 5.0) + '0');
20034599Sbostic }
20134599Sbostic }
20234599Sbostic /**/
20334599Sbostic /************************************************************************
20434599Sbostic /
20534599Sbostic / FUNCTION NAME: interrupt()
20634599Sbostic /
20734599Sbostic / FUNCTION: handle interrupt from operator
20834599Sbostic /
20934599Sbostic / AUTHOR: E. A. Estes, 12/4/85
21034599Sbostic /
21134599Sbostic / ARGUMENTS: none
21234599Sbostic /
21334599Sbostic / RETURN VALUE: none
21434599Sbostic /
21534599Sbostic / MODULES CALLED: fork(), exit(), wait(), death(), alarm(), execl(), wmove(),
21634599Sbostic / getgid(), signal(), getenv(), wclear(), setuid(), getuid(), setgid(),
21734599Sbostic / crmode(), clearok(), waddstr(), cleanup(), wrefresh(), leavegame(),
21834599Sbostic / getanswer()
21934599Sbostic /
22034599Sbostic / GLOBAL INPUTS: Player, *stdscr
22134599Sbostic /
22234599Sbostic / GLOBAL OUTPUTS: none
22334599Sbostic /
22434599Sbostic / DESCRIPTION:
22534599Sbostic / Allow player to quit upon hitting the interrupt key.
22634599Sbostic / If the player wants to quit while in battle, he/she automatically
22734599Sbostic / dies.
22834599Sbostic /
22934599Sbostic /************************************************************************/
23034599Sbostic
interrupt()23134599Sbostic interrupt()
23234599Sbostic {
23334599Sbostic char line[81]; /* a place to store data already on screen */
23434599Sbostic register int loop; /* counter */
23534599Sbostic int x, y; /* coordinates on screen */
23634599Sbostic int ch; /* input */
23734599Sbostic unsigned savealarm; /* to save alarm value */
23834599Sbostic
23934599Sbostic #ifdef SYS3
24034599Sbostic signal(SIGINT, SIG_IGN);
24134599Sbostic #endif
24234599Sbostic #ifdef SYS5
24334599Sbostic signal(SIGINT, SIG_IGN);
24434599Sbostic #endif
24534599Sbostic
24634599Sbostic savealarm = alarm(0); /* turn off any alarms */
24734599Sbostic
24834599Sbostic getyx(stdscr, y, x); /* save cursor location */
24934599Sbostic
25034599Sbostic for (loop = 0; loop < 80; ++loop) /* save line on screen */
25134599Sbostic {
25234599Sbostic move(4, loop);
25334599Sbostic line[loop] = inch();
25434599Sbostic }
25534599Sbostic line[80] = '\0'; /* nul terminate */
25634599Sbostic
25734599Sbostic if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER)
25834599Sbostic /* in midst of fighting */
25934599Sbostic {
26034599Sbostic mvaddstr(4, 0, "Quitting now will automatically kill your character. Still want to ? ");
26134599Sbostic ch = getanswer("NY", FALSE);
26234599Sbostic if (ch == 'Y')
26334599Sbostic death("Bailing out");
26434599Sbostic /*NOTREACHED*/
26534599Sbostic }
26634599Sbostic else
26734599Sbostic {
26834599Sbostic mvaddstr(4, 0, "Do you really want to quit ? ");
26934599Sbostic ch = getanswer("NY", FALSE);
27034599Sbostic if (ch == 'Y')
27134599Sbostic leavegame();
27234599Sbostic /*NOTREACHED*/
27334599Sbostic }
27434599Sbostic
27534599Sbostic mvaddstr(4, 0, line); /* restore data on screen */
27634599Sbostic move(y, x); /* restore cursor */
27734599Sbostic refresh();
27834599Sbostic
27934599Sbostic #ifdef SYS3
28034599Sbostic signal(SIGINT, interrupt);
28134599Sbostic #endif
28234599Sbostic #ifdef SYS5
28334599Sbostic signal(SIGINT, interrupt);
28434599Sbostic #endif
28534599Sbostic
28634599Sbostic alarm(savealarm); /* restore alarm */
28734599Sbostic }
28834599Sbostic /**/
28934599Sbostic /************************************************************************
29034599Sbostic /
29134599Sbostic / FUNCTION NAME: getanswer()
29234599Sbostic /
29334599Sbostic / FUNCTION: get an answer from operator
29434599Sbostic /
29534599Sbostic / AUTHOR: E. A. Estes, 12/4/85
29634599Sbostic /
29734599Sbostic / ARGUMENTS:
29834599Sbostic / char *choices - string of (upper case) valid choices
29934599Sbostic / bool def - set if default answer
30034599Sbostic /
30134599Sbostic / RETURN VALUE: none
30234599Sbostic /
30334599Sbostic / MODULES CALLED: alarm(), wmove(), waddch(), signal(), setjmp(), strchr(),
30434599Sbostic / _filbuf(), clearok(), toupper(), wrefresh(), mvprintw(), wclrtoeol()
30534599Sbostic /
30634599Sbostic / GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout,
30734599Sbostic / Timeoenv[]
30834599Sbostic /
30934599Sbostic / GLOBAL OUTPUTS: _iob[]
31034599Sbostic /
31134599Sbostic / DESCRIPTION:
31234599Sbostic / Get a single character answer from operator.
31334599Sbostic / Timeout waiting for response. If we timeout, or the
31434599Sbostic / answer in not in the list of valid choices, print choices,
31534599Sbostic / and wait again, otherwise return the first character in ths
31634599Sbostic / list of choices.
31734599Sbostic / Give up after 3 tries.
31834599Sbostic /
31934599Sbostic /************************************************************************/
32034599Sbostic
getanswer(choices,def)32134599Sbostic getanswer(choices, def)
32234599Sbostic char *choices;
32334599Sbostic bool def;
32434599Sbostic {
32534599Sbostic int ch; /* input */
32634599Sbostic int loop; /* counter */
32734599Sbostic int oldx, oldy; /* original coordinates on screen */
32834599Sbostic
32934599Sbostic getyx(stdscr, oldy, oldx);
33034599Sbostic alarm(0); /* make sure alarm is off */
33134599Sbostic
33234599Sbostic for (loop = 3; loop; --loop)
33334599Sbostic /* try for 3 times */
33434599Sbostic {
33534599Sbostic if (setjmp(Timeoenv) != 0)
33634599Sbostic /* timed out waiting for response */
33734599Sbostic {
33834599Sbostic if (def || loop <= 1)
33934599Sbostic /* return default answer */
34034599Sbostic break;
34134599Sbostic else
34234599Sbostic /* prompt, and try again */
34334599Sbostic goto YELL;
34434599Sbostic }
34534599Sbostic else
34634599Sbostic /* wait for response */
34734599Sbostic {
34834599Sbostic clrtoeol();
34934599Sbostic refresh();
35034599Sbostic #ifdef BSD41
35134599Sbostic sigset(SIGALRM, catchalarm);
35234599Sbostic #else
35334599Sbostic signal(SIGALRM, catchalarm);
35434599Sbostic #endif
35534599Sbostic /* set timeout */
35634599Sbostic if (Timeout)
35734599Sbostic alarm(7); /* short */
35834599Sbostic else
35934599Sbostic alarm(600); /* long */
36034599Sbostic
36134599Sbostic ch = getchar();
36234599Sbostic
36334599Sbostic alarm(0); /* turn off timeout */
36434599Sbostic
36534599Sbostic if (ch < 0)
36634599Sbostic /* caught some signal */
36734599Sbostic {
36834599Sbostic ++loop;
36934599Sbostic continue;
37034599Sbostic }
37134599Sbostic else if (ch == CH_REDRAW)
37234599Sbostic /* redraw screen */
37334599Sbostic {
37434599Sbostic clearok(stdscr, TRUE); /* force clear screen */
37534599Sbostic ++loop; /* don't count this input */
37634599Sbostic continue;
37734599Sbostic }
37834599Sbostic else if (Echo)
37934599Sbostic {
38034599Sbostic addch(ch); /* echo character */
38134599Sbostic refresh();
38234599Sbostic }
38334599Sbostic
38434599Sbostic if (islower(ch))
38534599Sbostic /* convert to upper case */
38634599Sbostic ch = toupper(ch);
38734599Sbostic
38834599Sbostic if (def || strchr(choices, ch) != NULL)
38934599Sbostic /* valid choice */
39034599Sbostic return(ch);
39134599Sbostic else if (!def && loop > 1)
39234599Sbostic /* bad choice; prompt, and try again */
39334599Sbostic {
39434599Sbostic YELL: mvprintw(oldy + 1, 0, "Please choose one of : [%s]\n", choices);
39534599Sbostic move(oldy, oldx);
39634599Sbostic clrtoeol();
39734599Sbostic continue;
39834599Sbostic }
39934599Sbostic else
40034599Sbostic /* return default answer */
40134599Sbostic break;
40234599Sbostic }
40334599Sbostic }
40434599Sbostic
40534599Sbostic return(*choices);
40634599Sbostic }
40734599Sbostic /**/
40834599Sbostic /************************************************************************
40934599Sbostic /
41034599Sbostic / FUNCTION NAME: catchalarm()
41134599Sbostic /
41234599Sbostic / FUNCTION: catch timer when waiting for input
41334599Sbostic /
41434599Sbostic / AUTHOR: E. A. Estes, 12/4/85
41534599Sbostic /
41634599Sbostic / ARGUMENTS: none
41734599Sbostic /
41834599Sbostic / RETURN VALUE: none
41934599Sbostic /
42034599Sbostic / MODULES CALLED: longjmp()
42134599Sbostic /
42234599Sbostic / GLOBAL INPUTS: Timeoenv[]
42334599Sbostic /
42434599Sbostic / GLOBAL OUTPUTS: none
42534599Sbostic /
42634599Sbostic / DESCRIPTION:
42734599Sbostic / Come here when the alarm expires while waiting for input.
42834599Sbostic / Simply longjmp() into getanswer().
42934599Sbostic /
43034599Sbostic /************************************************************************/
43134599Sbostic
432*56571Sbostic void
catchalarm()43334599Sbostic catchalarm()
43434599Sbostic {
43534599Sbostic longjmp(Timeoenv, 1);
43634599Sbostic }
437