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