powerd: Implement mwait C-state hint adjustment
[dragonfly.git] / games / phantasia / io.c
1 /*
2  * io.c - input/output routines for Phantasia
3  *
4  * $FreeBSD: src/games/phantasia/io.c,v 1.6 1999/11/16 02:57:33 billf Exp $
5  */
6
7 #include <string.h>
8 #include "include.h"
9
10 /* functions which we need to know about */
11 /* misc.c */
12 extern  void    death(const char *);
13 extern  void    leavegame(void);
14 /* phantglobs.c */
15 extern  double  drandom(void);
16
17 void    catchalarm(int);
18 int     getanswer(const char *, bool);
19 void    getstring(char *, int);
20 double  infloat(void);
21 int     inputoption(void);
22 void    interrupt(void);
23 void    more(int);
24
25 /*
26  * FUNCTION: read a string from operator
27  *
28  * ARGUMENTS:
29  *      char *cp - pointer to buffer area to fill
30  *      int mx - maximum number of characters to put in buffer
31  *
32  * GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
33  *
34  * GLOBAL OUTPUTS: _iob[]
35  *
36  * DESCRIPTION:
37  *      Read a string from the keyboard.
38  *      This routine is specially designed to:
39  *
40  *          - strip non-printing characters (unless Wizard)
41  *          - echo, if desired
42  *          - redraw the screen if CH_REDRAW is entered
43  *          - read in only 'mx - 1' characters or less characters
44  *          - nul-terminate string, and throw away newline
45  *
46  *      'mx' is assumed to be at least 2.
47  */
48
49 void
50 getstring(char *cp, int mx)
51 {
52         char *inptr;            /* pointer into string for next string */
53         int x, y;               /* original x, y coordinates on screen */
54         int ch;                 /* input */
55
56         getyx(stdscr, y, x);    /* get coordinates on screen */
57         inptr = cp;
58         *inptr = '\0';          /* clear string to start */
59         --mx;                   /* reserve room in string for nul terminator */
60
61         do {
62                 /* get characters and process */
63                 if (Echo)
64                         mvaddstr(y, x, cp);     /* print string on screen */
65                 clrtoeol();     /* clear any data after string */
66                 refresh();      /* update screen */
67
68                 ch = getchar(); /* get character */
69
70                 switch (ch) {
71                 case CH_ERASE:  /* back up one character */
72                         if (inptr > cp)
73                                 --inptr;
74                         break;
75
76                 case CH_KILL:   /* back up to original location */
77                         inptr = cp;
78                         break;
79
80                 case CH_NEWLINE:        /* terminate string */
81                         break;
82
83                 case CH_REDRAW: /* redraw screen */
84                         clearok(stdscr, TRUE);
85                         continue;
86
87                 default:        /* put data in string */
88                         if (ch >= ' ' || Wizard)
89                                 /* printing char; put in string */
90                                 *inptr++ = ch;
91                 }
92
93                 *inptr = '\0';  /* terminate string */
94         } while (ch != CH_NEWLINE && inptr < cp + mx);
95 }
96
97 /*
98  * FUNCTION: pause and prompt player
99  *
100  * ARGUMENTS:
101  *      int where - line on screen on which to pause
102  *
103  * GLOBAL INPUTS: *stdscr
104  *
105  * DESCRIPTION:
106  *      Print a message, and wait for a space character.
107  */
108
109 void
110 more(int where)
111 {
112         mvaddstr(where, 0, "-- more --");
113         getanswer(" ", FALSE);
114 }
115
116 /*
117  * FUNCTION: input a floating point number from operator
118  *
119  * RETURN VALUE: floating point number from operator
120  *
121  * GLOBAL INPUTS: Databuf[]
122  *
123  * DESCRIPTION:
124  *      Read a string from player, and scan for a floating point
125  *      number.
126  *      If no valid number is found, return 0.0.
127  */
128
129 double
130 infloat(void)
131 {
132         double result;          /* return value */
133
134         getstring(Databuf, SZ_DATABUF);
135         if (sscanf(Databuf, "%lf", &result) < 1)
136                 /* no valid number entered */
137                 result = 0.0;
138
139         return (result);
140 }
141
142 /*
143  * FUNCTION: input an option value from player
144  *
145  * GLOBAL INPUTS: Player
146  *
147  * GLOBAL OUTPUTS: Player
148  *
149  * DESCRIPTION:
150  *      Age increases with every move.
151  *      Refresh screen, and get a single character option from player.
152  *      Return a random value if player's ring has gone bad.
153  */
154
155 int
156 inputoption(void)
157 {
158         ++Player.p_age;         /* increase age */
159
160         if (Player.p_ring.ring_type != R_SPOILED)
161                 /* ring ok */
162                 return (getanswer("T ", TRUE));
163         else {
164                 /* bad ring */
165                 getanswer(" ", TRUE);
166                 return ((int)ROLL(0.0, 5.0) + '0');
167         }
168 }
169
170 /*
171  * FUNCTION: handle interrupt from operator
172  *
173  * GLOBAL INPUTS: Player, *stdscr
174  *
175  * DESCRIPTION:
176  *      Allow player to quit upon hitting the interrupt key.
177  *      If the player wants to quit while in battle, he/she automatically
178  *      dies.
179  */
180
181 void
182 interrupt(void)
183 {
184         char line[81];          /* a place to store data already on screen */
185         int loop;               /* counter */
186         int x, y;               /* coordinates on screen */
187         int ch;                 /* input */
188         unsigned savealarm;     /* to save alarm value */
189
190 #ifdef SYS3
191         signal(SIGINT, SIG_IGN);
192 #endif
193 #ifdef SYS5
194         signal(SIGINT, SIG_IGN);
195 #endif
196
197         savealarm = alarm(0);   /* turn off any alarms */
198
199         getyx(stdscr, y, x);    /* save cursor location */
200
201         for (loop = 0; loop < 80; ++loop) {     /* save line on screen */
202                 move(4, loop);
203                 line[loop] = inch();
204         }
205         line[80] = '\0';        /* nul terminate */
206
207         if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER) {
208                 /* in midst of fighting */
209                 mvaddstr(4, 0, "Quitting now will automatically kill your character.  Still want to ? ");
210                 ch = getanswer("NY", FALSE);
211                 if (ch == 'Y')
212                         death("Bailing out");
213                 /* NOTREACHED */
214         } else {
215                 mvaddstr(4, 0, "Do you really want to quit ? ");
216                 ch = getanswer("NY", FALSE);
217                 if (ch == 'Y')
218                         leavegame();
219                 /* NOTREACHED */
220         }
221
222         mvaddstr(4, 0, line);   /* restore data on screen */
223         move(y, x);             /* restore cursor */
224         refresh();
225
226 #ifdef SYS3
227         signal(SIGINT, interrupt);
228 #endif
229 #ifdef SYS5
230         signal(SIGINT, interrupt);
231 #endif
232
233         alarm(savealarm);       /* restore alarm */
234 }
235
236 /*
237  * FUNCTION: get an answer from operator
238  *
239  * ARGUMENTS:
240  *      char *choices - string of (upper case) valid choices
241  *      bool def - set if default answer
242  *
243  * GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout,
244  *      Timeoenv[]
245  *
246  * GLOBAL OUTPUTS: _iob[]
247  *
248  * DESCRIPTION:
249  *      Get a single character answer from operator.
250  *      Timeout waiting for response.  If we timeout, or the
251  *      answer in not in the list of valid choices, print choices,
252  *      and wait again, otherwise return the first character in ths
253  *      list of choices.
254  *      Give up after 3 tries.
255  */
256
257 int
258 getanswer(const char *choices, bool def)
259 {
260         int ch;                         /* input */
261         volatile int loop;              /* counter */
262         volatile int oldx, oldy;        /* original coordinates on screen */
263
264         getyx(stdscr, oldy, oldx);
265         alarm(0);                       /* make sure alarm is off */
266
267         for (loop = 3; loop; --loop) {
268                 /* try for 3 times */
269                 if (setjmp(Timeoenv) != 0) {
270                         /* timed out waiting for response */
271                         if (def || loop <= 1)
272                                 /* return default answer */
273                                 break;
274                         else
275                                 /* prompt, and try again */
276                                 goto YELL;
277                 } else {
278                         /* wait for response */
279                         clrtoeol();
280                         refresh();
281 #ifdef BSD41
282                         sigset(SIGALRM, catchalarm);
283 #else
284                         signal(SIGALRM, catchalarm);
285 #endif
286                         /* set timeout */
287                         if (Timeout)
288                                 alarm(7);       /* short */
289                         else
290                                 alarm(600);     /* long */
291
292                         ch = getchar();
293
294                         alarm(0);       /* turn off timeout */
295
296                         if (ch < 0) {
297                                 /* caught some signal */
298                                 ++loop;
299                                 continue;
300                         } else if (ch == CH_REDRAW)       {
301                                 /* redraw screen */
302                                 clearok(stdscr, TRUE);  /* force clear screen */
303                                 ++loop; /* don't count this input */
304                                 continue;
305                         } else if (Echo)       {
306                                 addch(ch);      /* echo character */
307                                 refresh();
308                         }
309
310                         if (islower(ch))
311                                 /* convert to upper case */
312                                 ch = toupper(ch);
313
314                         if (def || strchr(choices, ch) != NULL)
315                                 /* valid choice */
316                                 return (ch);
317                         else if (!def && loop > 1) {
318                                 /* bad choice; prompt, and try again */
319 YELL:                           mvprintw(oldy + 1, 0,
320                                     "Please choose one of : [%s]\n", choices);
321                                 move(oldy, oldx);
322                                 clrtoeol();
323                                 continue;
324                         } else
325                                 /* return default answer */
326                                 break;
327                 }
328         }
329
330         return (*choices);
331 }
332
333 /*
334  * FUNCTION: catch timer when waiting for input
335  *
336  * GLOBAL INPUTS: Timeoenv[]
337  *
338  * DESCRIPTION:
339  *      Come here when the alarm expires while waiting for input.
340  *      Simply longjmp() into getanswer().
341  */
342
343 void
344 catchalarm(__unused int sig)
345 {
346         longjmp(Timeoenv, 1);
347 }