Release Engineering: Update master to 2.3.0-DEVELOPMENT
[dragonfly.git] / games / phantasia / io.c
blobc9c9bd75ea3910b167b27dd0b7b6703362f501cf
1 /*
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 $
5 * $DragonFly: src/games/phantasia/io.c,v 1.3 2005/05/31 00:06:26 swildner Exp $
6 */
8 #include <string.h>
9 #include "include.h"
11 /* functions which we need to know about */
12 /* misc.c */
13 extern void death(const char *);
14 extern void leavegame(void);
15 /* phantglobs.c */
16 extern double drandom(void);
18 void getstring(char *, int);
19 void more(int);
20 double infloat(void);
21 int inputoption(void);
22 void interrupt(void);
23 int getanswer(const char *, bool);
24 void catchalarm(void);
26 /************************************************************************
28 / FUNCTION NAME: getstring()
30 / FUNCTION: read a string from operator
32 / AUTHOR: E. A. Estes, 12/4/85
34 / ARGUMENTS:
35 / char *cp - pointer to buffer area to fill
36 / int mx - maximum number of characters to put in buffer
38 / RETURN VALUE: none
40 / MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
41 / wclrtoeol()
43 / GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
45 / GLOBAL OUTPUTS: _iob[]
47 / DESCRIPTION:
48 / Read a string from the keyboard.
49 / This routine is specially designed to:
51 / - strip non-printing characters (unless Wizard)
52 / - echo, if desired
53 / - redraw the screen if CH_REDRAW is entered
54 / - read in only 'mx - 1' characters or less characters
55 / - nul-terminate string, and throw away newline
57 / 'mx' is assumed to be at least 2.
59 *************************************************************************/
61 void
62 getstring(char *cp, int mx)
64 char *inptr; /* pointer into string for next string */
65 int x, y; /* original x, y coordinates on screen */
66 int ch; /* input */
68 getyx(stdscr, y, x); /* get coordinates on screen */
69 inptr = cp;
70 *inptr = '\0'; /* clear string to start */
71 --mx; /* reserve room in string for nul terminator */
74 /* get characters and process */
76 if (Echo)
77 mvaddstr(y, x, cp); /* print string on screen */
78 clrtoeol(); /* clear any data after string */
79 refresh(); /* update screen */
81 ch = getchar(); /* get character */
83 switch (ch)
85 case CH_ERASE: /* back up one character */
86 if (inptr > cp)
87 --inptr;
88 break;
90 case CH_KILL: /* back up to original location */
91 inptr = cp;
92 break;
94 case CH_NEWLINE: /* terminate string */
95 break;
97 case CH_REDRAW: /* redraw screen */
98 clearok(stdscr, TRUE);
99 continue;
101 default: /* put data in string */
102 if (ch >= ' ' || Wizard)
103 /* printing char; put in string */
104 *inptr++ = ch;
107 *inptr = '\0'; /* terminate string */
109 while (ch != CH_NEWLINE && inptr < cp + mx);
111 /*\f*/
112 /************************************************************************
114 / FUNCTION NAME: more()
116 / FUNCTION: pause and prompt player
118 / AUTHOR: E. A. Estes, 12/4/85
120 / ARGUMENTS:
121 / int where - line on screen on which to pause
123 / RETURN VALUE: none
125 / MODULES CALLED: wmove(), waddstr(), getanswer()
127 / GLOBAL INPUTS: *stdscr
129 / GLOBAL OUTPUTS: none
131 / DESCRIPTION:
132 / Print a message, and wait for a space character.
134 *************************************************************************/
136 void
137 more(int where)
139 mvaddstr(where, 0, "-- more --");
140 getanswer(" ", FALSE);
142 /*\f*/
143 /************************************************************************
145 / FUNCTION NAME: infloat()
147 / FUNCTION: input a floating point number from operator
149 / AUTHOR: E. A. Estes, 12/4/85
151 / ARGUMENTS: none
153 / RETURN VALUE: floating point number from operator
155 / MODULES CALLED: sscanf(), getstring()
157 / GLOBAL INPUTS: Databuf[]
159 / GLOBAL OUTPUTS: none
161 / DESCRIPTION:
162 / Read a string from player, and scan for a floating point
163 / number.
164 / If no valid number is found, return 0.0.
166 *************************************************************************/
168 double
169 infloat(void)
171 double result; /* return value */
173 getstring(Databuf, SZ_DATABUF);
174 if (sscanf(Databuf, "%lf", &result) < 1)
175 /* no valid number entered */
176 result = 0.0;
178 return(result);
180 /*\f*/
181 /************************************************************************
183 / FUNCTION NAME: inputoption()
185 / FUNCTION: input an option value from player
187 / AUTHOR: E. A. Estes, 12/4/85
189 / ARGUMENTS: none
191 / RETURN VALUE: none
193 / MODULES CALLED: floor(), drandom(), getanswer()
195 / GLOBAL INPUTS: Player
197 / GLOBAL OUTPUTS: Player
199 / DESCRIPTION:
200 / Age increases with every move.
201 / Refresh screen, and get a single character option from player.
202 / Return a random value if player's ring has gone bad.
204 *************************************************************************/
207 inputoption(void)
209 ++Player.p_age; /* increase age */
211 if (Player.p_ring.ring_type != R_SPOILED)
212 /* ring ok */
213 return(getanswer("T ", TRUE));
214 else
215 /* bad ring */
217 getanswer(" ", TRUE);
218 return((int) ROLL(0.0, 5.0) + '0');
221 /*\f*/
222 /************************************************************************
224 / FUNCTION NAME: interrupt()
226 / FUNCTION: handle interrupt from operator
228 / AUTHOR: E. A. Estes, 12/4/85
230 / ARGUMENTS: none
232 / RETURN VALUE: none
234 / MODULES CALLED: fork(), exit(), wait(), death(), alarm(), execl(), wmove(),
235 / getgid(), signal(), getenv(), wclear(), setuid(), getuid(), setgid(),
236 / crmode(), clearok(), waddstr(), cleanup(), wrefresh(), leavegame(),
237 / getanswer()
239 / GLOBAL INPUTS: Player, *stdscr
241 / GLOBAL OUTPUTS: none
243 / DESCRIPTION:
244 / Allow player to quit upon hitting the interrupt key.
245 / If the player wants to quit while in battle, he/she automatically
246 / dies.
248 *************************************************************************/
250 void
251 interrupt(void)
253 char line[81]; /* a place to store data already on screen */
254 int loop; /* counter */
255 int x, y; /* coordinates on screen */
256 int ch; /* input */
257 unsigned savealarm; /* to save alarm value */
259 #ifdef SYS3
260 signal(SIGINT, SIG_IGN);
261 #endif
262 #ifdef SYS5
263 signal(SIGINT, SIG_IGN);
264 #endif
266 savealarm = alarm(0); /* turn off any alarms */
268 getyx(stdscr, y, x); /* save cursor location */
270 for (loop = 0; loop < 80; ++loop) /* save line on screen */
272 move(4, loop);
273 line[loop] = inch();
275 line[80] = '\0'; /* nul terminate */
277 if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER)
278 /* in midst of fighting */
280 mvaddstr(4, 0, "Quitting now will automatically kill your character. Still want to ? ");
281 ch = getanswer("NY", FALSE);
282 if (ch == 'Y')
283 death("Bailing out");
284 /*NOTREACHED*/
286 else
288 mvaddstr(4, 0, "Do you really want to quit ? ");
289 ch = getanswer("NY", FALSE);
290 if (ch == 'Y')
291 leavegame();
292 /*NOTREACHED*/
295 mvaddstr(4, 0, line); /* restore data on screen */
296 move(y, x); /* restore cursor */
297 refresh();
299 #ifdef SYS3
300 signal(SIGINT, interrupt);
301 #endif
302 #ifdef SYS5
303 signal(SIGINT, interrupt);
304 #endif
306 alarm(savealarm); /* restore alarm */
308 /*\f*/
309 /************************************************************************
311 / FUNCTION NAME: getanswer()
313 / FUNCTION: get an answer from operator
315 / AUTHOR: E. A. Estes, 12/4/85
317 / ARGUMENTS:
318 / char *choices - string of (upper case) valid choices
319 / bool def - set if default answer
321 / RETURN VALUE: none
323 / MODULES CALLED: alarm(), wmove(), waddch(), signal(), setjmp(), strchr(),
324 / _filbuf(), clearok(), toupper(), wrefresh(), mvprintw(), wclrtoeol()
326 / GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout,
327 / Timeoenv[]
329 / GLOBAL OUTPUTS: _iob[]
331 / DESCRIPTION:
332 / Get a single character answer from operator.
333 / Timeout waiting for response. If we timeout, or the
334 / answer in not in the list of valid choices, print choices,
335 / and wait again, otherwise return the first character in ths
336 / list of choices.
337 / Give up after 3 tries.
339 *************************************************************************/
342 getanswer(const char *choices, bool def)
344 int ch; /* input */
345 volatile int loop; /* counter */
346 volatile int oldx, oldy; /* original coordinates on screen */
348 getyx(stdscr, oldy, oldx);
349 alarm(0); /* make sure alarm is off */
351 for (loop = 3; loop; --loop)
352 /* try for 3 times */
354 if (setjmp(Timeoenv) != 0)
355 /* timed out waiting for response */
357 if (def || loop <= 1)
358 /* return default answer */
359 break;
360 else
361 /* prompt, and try again */
362 goto YELL;
364 else
365 /* wait for response */
367 clrtoeol();
368 refresh();
369 #ifdef BSD41
370 sigset(SIGALRM, catchalarm);
371 #else
372 signal(SIGALRM, (sig_t)catchalarm);
373 #endif
374 /* set timeout */
375 if (Timeout)
376 alarm(7); /* short */
377 else
378 alarm(600); /* long */
380 ch = getchar();
382 alarm(0); /* turn off timeout */
384 if (ch < 0)
385 /* caught some signal */
387 ++loop;
388 continue;
390 else if (ch == CH_REDRAW)
391 /* redraw screen */
393 clearok(stdscr, TRUE); /* force clear screen */
394 ++loop; /* don't count this input */
395 continue;
397 else if (Echo)
399 addch(ch); /* echo character */
400 refresh();
403 if (islower(ch))
404 /* convert to upper case */
405 ch = toupper(ch);
407 if (def || strchr(choices, ch) != NULL)
408 /* valid choice */
409 return(ch);
410 else if (!def && loop > 1)
411 /* bad choice; prompt, and try again */
413 YELL: mvprintw(oldy + 1, 0, "Please choose one of : [%s]\n", choices);
414 move(oldy, oldx);
415 clrtoeol();
416 continue;
418 else
419 /* return default answer */
420 break;
424 return(*choices);
426 /*\f*/
427 /************************************************************************
429 / FUNCTION NAME: catchalarm()
431 / FUNCTION: catch timer when waiting for input
433 / AUTHOR: E. A. Estes, 12/4/85
435 / ARGUMENTS: none
437 / RETURN VALUE: none
439 / MODULES CALLED: longjmp()
441 / GLOBAL INPUTS: Timeoenv[]
443 / GLOBAL OUTPUTS: none
445 / DESCRIPTION:
446 / Come here when the alarm expires while waiting for input.
447 / Simply longjmp() into getanswer().
449 *************************************************************************/
451 void
452 catchalarm(void)
454 longjmp(Timeoenv, 1);