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