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