Clean up:
[dragonfly.git] / games / phantasia / io.c
CommitLineData
984263bc
MD
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 $
1de703da 5 * $DragonFly: src/games/phantasia/io.c,v 1.2 2003/06/17 04:25:24 dillon Exp $
984263bc
MD
6 */
7
8#include <string.h>
9#include "include.h"
10
11/************************************************************************
12/
13/ FUNCTION NAME: getstring()
14/
15/ FUNCTION: read a string from operator
16/
17/ AUTHOR: E. A. Estes, 12/4/85
18/
19/ ARGUMENTS:
20/ char *cp - pointer to buffer area to fill
21/ int mx - maximum number of characters to put in buffer
22/
23/ RETURN VALUE: none
24/
25/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
26/ wclrtoeol()
27/
28/ GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
29/
30/ GLOBAL OUTPUTS: _iob[]
31/
32/ DESCRIPTION:
33/ Read a string from the keyboard.
34/ This routine is specially designed to:
35/
36/ - strip non-printing characters (unless Wizard)
37/ - echo, if desired
38/ - redraw the screen if CH_REDRAW is entered
39/ - read in only 'mx - 1' characters or less characters
40/ - nul-terminate string, and throw away newline
41/
42/ 'mx' is assumed to be at least 2.
43/
44*************************************************************************/
45
46getstring(cp, mx)
47char *cp;
48int mx;
49{
50char *inptr; /* pointer into string for next string */
51int x, y; /* original x, y coordinates on screen */
52int ch; /* input */
53
54 getyx(stdscr, y, x); /* get coordinates on screen */
55 inptr = cp;
56 *inptr = '\0'; /* clear string to start */
57 --mx; /* reserve room in string for nul terminator */
58
59 do
60 /* get characters and process */
61 {
62 if (Echo)
63 mvaddstr(y, x, cp); /* print string on screen */
64 clrtoeol(); /* clear any data after string */
65 refresh(); /* update screen */
66
67 ch = getchar(); /* get character */
68
69 switch (ch)
70 {
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 }
95 while (ch != CH_NEWLINE && inptr < cp + mx);
96}
97/*\f*/
98/************************************************************************
99/
100/ FUNCTION NAME: more()
101/
102/ FUNCTION: pause and prompt player
103/
104/ AUTHOR: E. A. Estes, 12/4/85
105/
106/ ARGUMENTS:
107/ int where - line on screen on which to pause
108/
109/ RETURN VALUE: none
110/
111/ MODULES CALLED: wmove(), waddstr(), getanswer()
112/
113/ GLOBAL INPUTS: *stdscr
114/
115/ GLOBAL OUTPUTS: none
116/
117/ DESCRIPTION:
118/ Print a message, and wait for a space character.
119/
120*************************************************************************/
121
122more(where)
123int where;
124{
125 mvaddstr(where, 0, "-- more --");
126 getanswer(" ", FALSE);
127}
128/*\f*/
129/************************************************************************
130/
131/ FUNCTION NAME: infloat()
132/
133/ FUNCTION: input a floating point number from operator
134/
135/ AUTHOR: E. A. Estes, 12/4/85
136/
137/ ARGUMENTS: none
138/
139/ RETURN VALUE: floating point number from operator
140/
141/ MODULES CALLED: sscanf(), getstring()
142/
143/ GLOBAL INPUTS: Databuf[]
144/
145/ GLOBAL OUTPUTS: none
146/
147/ DESCRIPTION:
148/ Read a string from player, and scan for a floating point
149/ number.
150/ If no valid number is found, return 0.0.
151/
152*************************************************************************/
153
154double
155infloat()
156{
157double result; /* return value */
158
159 getstring(Databuf, SZ_DATABUF);
160 if (sscanf(Databuf, "%lf", &result) < 1)
161 /* no valid number entered */
162 result = 0.0;
163
164 return(result);
165}
166/*\f*/
167/************************************************************************
168/
169/ FUNCTION NAME: inputoption()
170/
171/ FUNCTION: input an option value from player
172/
173/ AUTHOR: E. A. Estes, 12/4/85
174/
175/ ARGUMENTS: none
176/
177/ RETURN VALUE: none
178/
179/ MODULES CALLED: floor(), drandom(), getanswer()
180/
181/ GLOBAL INPUTS: Player
182/
183/ GLOBAL OUTPUTS: Player
184/
185/ DESCRIPTION:
186/ Age increases with every move.
187/ Refresh screen, and get a single character option from player.
188/ Return a random value if player's ring has gone bad.
189/
190*************************************************************************/
191
192inputoption()
193{
194 ++Player.p_age; /* increase age */
195
196 if (Player.p_ring.ring_type != R_SPOILED)
197 /* ring ok */
198 return(getanswer("T ", TRUE));
199 else
200 /* bad ring */
201 {
202 getanswer(" ", TRUE);
203 return((int) ROLL(0.0, 5.0) + '0');
204 }
205}
206/*\f*/
207/************************************************************************
208/
209/ FUNCTION NAME: interrupt()
210/
211/ FUNCTION: handle interrupt from operator
212/
213/ AUTHOR: E. A. Estes, 12/4/85
214/
215/ ARGUMENTS: none
216/
217/ RETURN VALUE: none
218/
219/ MODULES CALLED: fork(), exit(), wait(), death(), alarm(), execl(), wmove(),
220/ getgid(), signal(), getenv(), wclear(), setuid(), getuid(), setgid(),
221/ crmode(), clearok(), waddstr(), cleanup(), wrefresh(), leavegame(),
222/ getanswer()
223/
224/ GLOBAL INPUTS: Player, *stdscr
225/
226/ GLOBAL OUTPUTS: none
227/
228/ DESCRIPTION:
229/ Allow player to quit upon hitting the interrupt key.
230/ If the player wants to quit while in battle, he/she automatically
231/ dies.
232/
233*************************************************************************/
234
235interrupt()
236{
237char line[81]; /* a place to store data already on screen */
238int loop; /* counter */
239int x, y; /* coordinates on screen */
240int ch; /* input */
241unsigned savealarm; /* to save alarm value */
242
243#ifdef SYS3
244 signal(SIGINT, SIG_IGN);
245#endif
246#ifdef SYS5
247 signal(SIGINT, SIG_IGN);
248#endif
249
250 savealarm = alarm(0); /* turn off any alarms */
251
252 getyx(stdscr, y, x); /* save cursor location */
253
254 for (loop = 0; loop < 80; ++loop) /* save line on screen */
255 {
256 move(4, loop);
257 line[loop] = inch();
258 }
259 line[80] = '\0'; /* nul terminate */
260
261 if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER)
262 /* in midst of fighting */
263 {
264 mvaddstr(4, 0, "Quitting now will automatically kill your character. Still want to ? ");
265 ch = getanswer("NY", FALSE);
266 if (ch == 'Y')
267 death("Bailing out");
268 /*NOTREACHED*/
269 }
270 else
271 {
272 mvaddstr(4, 0, "Do you really want to quit ? ");
273 ch = getanswer("NY", FALSE);
274 if (ch == 'Y')
275 leavegame();
276 /*NOTREACHED*/
277 }
278
279 mvaddstr(4, 0, line); /* restore data on screen */
280 move(y, x); /* restore cursor */
281 refresh();
282
283#ifdef SYS3
284 signal(SIGINT, interrupt);
285#endif
286#ifdef SYS5
287 signal(SIGINT, interrupt);
288#endif
289
290 alarm(savealarm); /* restore alarm */
291}
292/*\f*/
293/************************************************************************
294/
295/ FUNCTION NAME: getanswer()
296/
297/ FUNCTION: get an answer from operator
298/
299/ AUTHOR: E. A. Estes, 12/4/85
300/
301/ ARGUMENTS:
302/ char *choices - string of (upper case) valid choices
303/ bool def - set if default answer
304/
305/ RETURN VALUE: none
306/
307/ MODULES CALLED: alarm(), wmove(), waddch(), signal(), setjmp(), strchr(),
308/ _filbuf(), clearok(), toupper(), wrefresh(), mvprintw(), wclrtoeol()
309/
310/ GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout,
311/ Timeoenv[]
312/
313/ GLOBAL OUTPUTS: _iob[]
314/
315/ DESCRIPTION:
316/ Get a single character answer from operator.
317/ Timeout waiting for response. If we timeout, or the
318/ answer in not in the list of valid choices, print choices,
319/ and wait again, otherwise return the first character in ths
320/ list of choices.
321/ Give up after 3 tries.
322/
323*************************************************************************/
324
325getanswer(choices, def)
326char *choices;
327bool def;
328{
329int ch; /* input */
330int loop; /* counter */
331int oldx, oldy; /* original coordinates on screen */
332
333 getyx(stdscr, oldy, oldx);
334 alarm(0); /* make sure alarm is off */
335
336 for (loop = 3; loop; --loop)
337 /* try for 3 times */
338 {
339 if (setjmp(Timeoenv) != 0)
340 /* timed out waiting for response */
341 {
342 if (def || loop <= 1)
343 /* return default answer */
344 break;
345 else
346 /* prompt, and try again */
347 goto YELL;
348 }
349 else
350 /* wait for response */
351 {
352 clrtoeol();
353 refresh();
354#ifdef BSD41
355 sigset(SIGALRM, catchalarm);
356#else
357 signal(SIGALRM, catchalarm);
358#endif
359 /* set timeout */
360 if (Timeout)
361 alarm(7); /* short */
362 else
363 alarm(600); /* long */
364
365 ch = getchar();
366
367 alarm(0); /* turn off timeout */
368
369 if (ch < 0)
370 /* caught some signal */
371 {
372 ++loop;
373 continue;
374 }
375 else if (ch == CH_REDRAW)
376 /* redraw screen */
377 {
378 clearok(stdscr, TRUE); /* force clear screen */
379 ++loop; /* don't count this input */
380 continue;
381 }
382 else if (Echo)
383 {
384 addch(ch); /* echo character */
385 refresh();
386 }
387
388 if (islower(ch))
389 /* convert to upper case */
390 ch = toupper(ch);
391
392 if (def || strchr(choices, ch) != NULL)
393 /* valid choice */
394 return(ch);
395 else if (!def && loop > 1)
396 /* bad choice; prompt, and try again */
397 {
398YELL: mvprintw(oldy + 1, 0, "Please choose one of : [%s]\n", choices);
399 move(oldy, oldx);
400 clrtoeol();
401 continue;
402 }
403 else
404 /* return default answer */
405 break;
406 }
407 }
408
409 return(*choices);
410}
411/*\f*/
412/************************************************************************
413/
414/ FUNCTION NAME: catchalarm()
415/
416/ FUNCTION: catch timer when waiting for input
417/
418/ AUTHOR: E. A. Estes, 12/4/85
419/
420/ ARGUMENTS: none
421/
422/ RETURN VALUE: none
423/
424/ MODULES CALLED: longjmp()
425/
426/ GLOBAL INPUTS: Timeoenv[]
427/
428/ GLOBAL OUTPUTS: none
429/
430/ DESCRIPTION:
431/ Come here when the alarm expires while waiting for input.
432/ Simply longjmp() into getanswer().
433/
434*************************************************************************/
435
436void
437catchalarm()
438{
439 longjmp(Timeoenv, 1);
440}