2 * io.c - input/output routines for Phantasia
4 * $FreeBSD: src/games/phantasia/io.c,v 1.6 1999/11/16 02:57:33 billf Exp $
10 /************************************************************************
12 / FUNCTION NAME: getstring()
14 / FUNCTION: read a string from operator
16 / AUTHOR: E. A. Estes, 12/4/85
19 / char *cp - pointer to buffer area to fill
20 / int mx - maximum number of characters to put in buffer
24 / MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
27 / GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
29 / GLOBAL OUTPUTS: _iob[]
32 / Read a string from the keyboard.
33 / This routine is specially designed to:
35 / - strip non-printing characters (unless Wizard)
37 / - redraw the screen if CH_REDRAW is entered
38 / - read in only 'mx - 1' characters or less characters
39 / - nul-terminate string, and throw away newline
41 / 'mx' is assumed to be at least 2.
43 *************************************************************************/
49 char *inptr; /* pointer into string for next string */
50 int x, y; /* original x, y coordinates on screen */
53 getyx(stdscr, y, x); /* get coordinates on screen */
55 *inptr = '\0'; /* clear string to start */
56 --mx; /* reserve room in string for nul terminator */
59 /* get characters and process */
62 mvaddstr(y, x, cp); /* print string on screen */
63 clrtoeol(); /* clear any data after string */
64 refresh(); /* update screen */
66 ch = getchar(); /* get character */
70 case CH_ERASE: /* back up one character */
75 case CH_KILL: /* back up to original location */
79 case CH_NEWLINE: /* terminate string */
82 case CH_REDRAW: /* redraw screen */
83 clearok(stdscr, TRUE);
86 default: /* put data in string */
87 if (ch >= ' ' || Wizard)
88 /* printing char; put in string */
92 *inptr = '\0'; /* terminate string */
94 while (ch != CH_NEWLINE && inptr < cp + mx);
97 /************************************************************************
99 / FUNCTION NAME: more()
101 / FUNCTION: pause and prompt player
103 / AUTHOR: E. A. Estes, 12/4/85
106 / int where - line on screen on which to pause
110 / MODULES CALLED: wmove(), waddstr(), getanswer()
112 / GLOBAL INPUTS: *stdscr
114 / GLOBAL OUTPUTS: none
117 / Print a message, and wait for a space character.
119 *************************************************************************/
124 mvaddstr(where, 0, "-- more --");
125 getanswer(" ", FALSE);
128 /************************************************************************
130 / FUNCTION NAME: infloat()
132 / FUNCTION: input a floating point number from operator
134 / AUTHOR: E. A. Estes, 12/4/85
138 / RETURN VALUE: floating point number from operator
140 / MODULES CALLED: sscanf(), getstring()
142 / GLOBAL INPUTS: Databuf[]
144 / GLOBAL OUTPUTS: none
147 / Read a string from player, and scan for a floating point
149 / If no valid number is found, return 0.0.
151 *************************************************************************/
156 double result; /* return value */
158 getstring(Databuf, SZ_DATABUF);
159 if (sscanf(Databuf, "%lf", &result) < 1)
160 /* no valid number entered */
166 /************************************************************************
168 / FUNCTION NAME: inputoption()
170 / FUNCTION: input an option value from player
172 / AUTHOR: E. A. Estes, 12/4/85
178 / MODULES CALLED: floor(), drandom(), getanswer()
180 / GLOBAL INPUTS: Player
182 / GLOBAL OUTPUTS: Player
185 / Age increases with every move.
186 / Refresh screen, and get a single character option from player.
187 / Return a random value if player's ring has gone bad.
189 *************************************************************************/
193 ++Player.p_age; /* increase age */
195 if (Player.p_ring.ring_type != R_SPOILED)
197 return(getanswer("T ", TRUE));
201 getanswer(" ", TRUE);
202 return((int) ROLL(0.0, 5.0) + '0');
206 /************************************************************************
208 / FUNCTION NAME: interrupt()
210 / FUNCTION: handle interrupt from operator
212 / AUTHOR: E. A. Estes, 12/4/85
218 / MODULES CALLED: fork(), exit(), wait(), death(), alarm(), execl(), wmove(),
219 / getgid(), signal(), getenv(), wclear(), setuid(), getuid(), setgid(),
220 / crmode(), clearok(), waddstr(), cleanup(), wrefresh(), leavegame(),
223 / GLOBAL INPUTS: Player, *stdscr
225 / GLOBAL OUTPUTS: none
228 / Allow player to quit upon hitting the interrupt key.
229 / If the player wants to quit while in battle, he/she automatically
232 *************************************************************************/
236 char line[81]; /* a place to store data already on screen */
237 int loop; /* counter */
238 int x, y; /* coordinates on screen */
240 unsigned savealarm; /* to save alarm value */
243 signal(SIGINT, SIG_IGN);
246 signal(SIGINT, SIG_IGN);
249 savealarm = alarm(0); /* turn off any alarms */
251 getyx(stdscr, y, x); /* save cursor location */
253 for (loop = 0; loop < 80; ++loop) /* save line on screen */
258 line[80] = '\0'; /* nul terminate */
260 if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER)
261 /* in midst of fighting */
263 mvaddstr(4, 0, "Quitting now will automatically kill your character. Still want to ? ");
264 ch = getanswer("NY", FALSE);
266 death("Bailing out");
271 mvaddstr(4, 0, "Do you really want to quit ? ");
272 ch = getanswer("NY", FALSE);
278 mvaddstr(4, 0, line); /* restore data on screen */
279 move(y, x); /* restore cursor */
283 signal(SIGINT, interrupt);
286 signal(SIGINT, interrupt);
289 alarm(savealarm); /* restore alarm */
292 /************************************************************************
294 / FUNCTION NAME: getanswer()
296 / FUNCTION: get an answer from operator
298 / AUTHOR: E. A. Estes, 12/4/85
301 / char *choices - string of (upper case) valid choices
302 / bool def - set if default answer
306 / MODULES CALLED: alarm(), wmove(), waddch(), signal(), setjmp(), strchr(),
307 / _filbuf(), clearok(), toupper(), wrefresh(), mvprintw(), wclrtoeol()
309 / GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout,
312 / GLOBAL OUTPUTS: _iob[]
315 / Get a single character answer from operator.
316 / Timeout waiting for response. If we timeout, or the
317 / answer in not in the list of valid choices, print choices,
318 / and wait again, otherwise return the first character in ths
320 / Give up after 3 tries.
322 *************************************************************************/
324 getanswer(choices, def)
329 int loop; /* counter */
330 int oldx, oldy; /* original coordinates on screen */
332 getyx(stdscr, oldy, oldx);
333 alarm(0); /* make sure alarm is off */
335 for (loop = 3; loop; --loop)
336 /* try for 3 times */
338 if (setjmp(Timeoenv) != 0)
339 /* timed out waiting for response */
341 if (def || loop <= 1)
342 /* return default answer */
345 /* prompt, and try again */
349 /* wait for response */
354 sigset(SIGALRM, catchalarm);
356 signal(SIGALRM, catchalarm);
360 alarm(7); /* short */
362 alarm(600); /* long */
366 alarm(0); /* turn off timeout */
369 /* caught some signal */
374 else if (ch == CH_REDRAW)
377 clearok(stdscr, TRUE); /* force clear screen */
378 ++loop; /* don't count this input */
383 addch(ch); /* echo character */
388 /* convert to upper case */
391 if (def || strchr(choices, ch) != NULL)
394 else if (!def && loop > 1)
395 /* bad choice; prompt, and try again */
397 YELL: mvprintw(oldy + 1, 0, "Please choose one of : [%s]\n", choices);
403 /* return default answer */
411 /************************************************************************
413 / FUNCTION NAME: catchalarm()
415 / FUNCTION: catch timer when waiting for input
417 / AUTHOR: E. A. Estes, 12/4/85
423 / MODULES CALLED: longjmp()
425 / GLOBAL INPUTS: Timeoenv[]
427 / GLOBAL OUTPUTS: none
430 / Come here when the alarm expires while waiting for input.
431 / Simply longjmp() into getanswer().
433 *************************************************************************/
438 longjmp(Timeoenv, 1);