Annotation of early-roguelike/arogue7/io.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * io.c - Various input/output functions
3: *
4: * Advanced Rogue
5: * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
6: * All rights reserved.
7: *
8: * Based on "Rogue: Exploring the Dungeons of Doom"
9: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
10: * All rights reserved.
11: *
12: * See the file LICENSE.TXT for full copyright and licensing information.
13: */
14:
15: /*
16: * Various input/output functions
17: */
18:
19: #include "curses.h"
20: #include <stdarg.h>
21: #include <ctype.h>
22: #include <string.h>
23: #include "rogue.h"
24:
25: /*
26: * msg:
27: * Display a message at the top of the screen.
28: */
29:
30: static char msgbuf[BUFSIZ];
31: static int newpos = 0;
32:
33: void doadd(char *fmt, va_list ap);
34:
35: /*VARARGS1*/
36: void
37: msg(char *fmt, ...)
38: {
39: va_list ap;
40: /*
41: * if the string is "", just clear the line
42: */
43: if (*fmt == '\0')
44: {
45: overwrite(cw,msgw);
46: wmove(msgw, 0, 0);
47: clearok(msgw, FALSE);
48: draw(msgw);
49: mpos = 0;
50: return;
51: }
52: /*
53: * otherwise add to the message and flush it out
54: */
55: va_start(ap,fmt);
56: doadd(fmt, ap);
57: va_end(ap);
58: endmsg();
59: }
60:
61: /*
62: * add things to the current message
63: */
64: void
65: addmsg(char *fmt, ...)
66: {
67: va_list ap;
68:
69: va_start(ap, fmt);
70: doadd(fmt, ap);
71: va_end(ap);
72: }
73:
74: /*
75: * Display a new msg (giving him a chance to see the previous one if it
76: * is up there with the --More--)
77: */
78: void
79: endmsg(void)
80: {
81: /* Needed to track where we are for 5.0 (PC) curses */
82: register int x, y;
83:
84: strcpy(huh, msgbuf);
85: if (mpos) {
86: /*
87: * If this message will fit on the line (plus space for --More--
88: * then just add it (only during combat).
89: */
90: if (player.t_quiet < 0 && mpos + newpos + strlen(morestr) + 2 < cols) {
91: wmove(msgw, 0, mpos + 2);
92: newpos += mpos + 2;
93: }
94: else {
95: wmove(msgw, 0, mpos);
96: waddstr(msgw, morestr);
97: draw(cw);
98: draw(msgw);
99: wait_for(' ');
100: overwrite(cw,msgw);
101: wmove(msgw, 0, 0);
102: touchwin(cw);
103: }
104: }
105: else {
106: overwrite(cw,msgw);
107: wmove(msgw, 0, 0);
108: }
109: waddstr(msgw, msgbuf);
110: getyx(msgw, y, x);
111: mpos = newpos;
112: newpos = 0;
113: wmove(msgw, y, x);
114: draw(cw);
115: clearok(msgw, FALSE);
116: draw(msgw);
117: }
118:
119: void
120: doadd(char *fmt, va_list ap)
121: {
122:
123: /*
124: * Do the printf into buf
125: */
126: vsprintf(&msgbuf[newpos], fmt, ap);
127: newpos = strlen(msgbuf);
128: }
129:
130: /*
131: * step_ok:
132: * returns true if it is ok for type to step on ch
133: * flgptr will be NULL if we don't know what the monster is yet!
134: */
135:
136: bool
137: step_ok(int y, int x, int can_on_monst, struct thing *flgptr)
138: {
139: /* can_on_monst = MONSTOK if all we care about are physical obstacles */
140: register struct linked_list *item;
141: register struct thing *tp;
142: char ch;
143:
144: /* What is here? Don't check monster window if MONSTOK is set */
145: if (can_on_monst == MONSTOK) ch = CCHAR( mvinch(y, x) );
146: else ch = CCHAR( winat(y, x) );
147:
148: if (can_on_monst == FIGHTOK && isalpha(ch) &&
149: (item = find_mons(y, x)) != NULL) {
150: tp = THINGPTR(item); /* What monster is here? */
151:
152: /* We can hit it if we're after it */
153: if (flgptr->t_dest == &tp->t_pos) return TRUE;
154:
155: /*
156: * Otherwise, if we're friendly we'll hit it unless it is also
157: * friendly or is our race.
158: */
159: if (off(*flgptr, ISFRIENDLY) ||
160: on(*tp, ISFRIENDLY) ||
161: flgptr->t_index == tp->t_index) return FALSE;
162: else return TRUE;
163: }
164: else switch (ch)
165: {
166: case ' ':
167: case '|':
168: case '-':
169: case SECRETDOOR:
170: if (flgptr && on(*flgptr, CANINWALL)) return(TRUE);
171: return FALSE;
172: when SCROLL:
173: if (can_on_monst == MONSTOK) return(TRUE); /* Not a real obstacle */
174: /*
175: * If it is a scroll, it might be a scare monster scroll
176: * so we need to look it up to see what type it is.
177: */
178: if (flgptr && flgptr->t_ctype == C_MONSTER) {
179: item = find_obj(y, x);
180: if (item != NULL &&
181: (OBJPTR(item))->o_which==S_SCARE &&
182: (flgptr == NULL || flgptr->t_stats.s_intel < 16))
183: return(FALSE); /* All but smart ones are scared */
184: }
185: return(TRUE);
186: otherwise:
187: return (!isalpha(ch));
188: }
189: return(FALSE);
190: }
191: /*
192: * shoot_ok:
193: * returns true if it is ok for type to shoot over ch
194: */
195:
196: bool
197: shoot_ok(char ch)
198: {
199: switch (ch)
200: {
201: case ' ':
202: case '|':
203: case '-':
204: case SECRETDOOR:
205: case FOREST:
206: return FALSE;
207: default:
208: return (!isalpha(ch));
209: }
210: }
211:
212: /*
213: * readchar:
214: * flushes stdout so that screen is up to date and then returns
215: * getchar.
216: */
217:
218: int
219: readchar(void)
220: {
221: int ch;
222:
223: ch = md_readchar(cw);
224:
225: if ((ch == 3) || (ch == 0))
226: {
227: quit(0);
228: return(27);
229: }
230:
231: return(ch);
232: }
233:
234: /*
235: * status:
236: * Display the important stats line. Keep the cursor where it was.
237: * display: if TRUE, display unconditionally
238: */
239:
240: void
241: status(bool display)
242: {
243: register struct stats *stat_ptr, *max_ptr;
244: register int oy, ox, temp;
245: register char *pb;
246: static char buf[LINELEN];
247: static int hpwidth = 0, s_hungry = -1;
248: static int s_lvl = -1, s_hp = -1, s_str, maxs_str,
249: s_ac = 0;
250: static short s_intel, s_dext, s_wisdom, s_const, s_charisma;
251: static short maxs_intel, maxs_dext, maxs_wisdom, maxs_const, maxs_charisma;
252: static unsigned long s_exp = 0;
253: static int s_carry, s_pack;
254: bool first_line=FALSE;
255:
256: stat_ptr = &pstats;
257: max_ptr = &max_stats;
258:
259: /*
260: * If nothing has changed in the first line, then skip it
261: */
262: if (!display &&
263: s_lvl == level &&
264: s_intel == stat_ptr->s_intel &&
265: s_wisdom == stat_ptr->s_wisdom &&
266: s_dext == dex_compute() &&
267: s_const == stat_ptr->s_const &&
268: s_charisma == stat_ptr->s_charisma &&
269: s_str == str_compute() &&
270: s_hungry == hungry_state &&
271: maxs_intel == max_ptr->s_intel &&
272: maxs_wisdom == max_ptr->s_wisdom &&
273: maxs_dext == max_ptr->s_dext &&
274: maxs_const == max_ptr->s_const &&
275: maxs_charisma == max_ptr->s_charisma &&
276: maxs_str == max_ptr->s_str ) goto line_two;
277:
278: /* Display the first line */
279: first_line = TRUE;
280: getyx(cw, oy, ox);
281: sprintf(buf, "Int:%d(%d) Str:%d", stat_ptr->s_intel,
282: max_ptr->s_intel, str_compute());
283:
284: /* Maximum strength */
285: pb = &buf[strlen(buf)];
286: sprintf(pb, "(%d)", max_ptr->s_str);
287:
288: pb = &buf[strlen(buf)];
289: sprintf(pb, " Wis:%d(%d) Dxt:%d(%d) Con:%d(%d) Cha:%d(%d)",
290: stat_ptr->s_wisdom,max_ptr->s_wisdom,dex_compute(),max_ptr->s_dext,
291: stat_ptr->s_const,max_ptr->s_const,stat_ptr->s_charisma,
292: max_ptr->s_charisma);
293:
294: /* Update first line status */
295: s_intel = stat_ptr->s_intel;
296: s_wisdom = stat_ptr->s_wisdom;
297: s_dext = dex_compute();
298: s_const = stat_ptr->s_const;
299: s_charisma = stat_ptr->s_charisma;
300: s_str = str_compute();
301: maxs_intel = max_ptr->s_intel;
302: maxs_wisdom = max_ptr->s_wisdom;
303: maxs_dext = max_ptr->s_dext;
304: maxs_const = max_ptr->s_const;
305: maxs_charisma = max_ptr->s_charisma;
306: maxs_str = max_ptr->s_str;
307:
308: /* Print the line */
309: mvwaddstr(cw, lines - 2, 0, buf);
310: switch (hungry_state)
311: {
312: case F_SATIATED:
313: waddstr(cw, " Satiated");
314: when F_OKAY: ;
315: when F_HUNGRY:
316: waddstr(cw, " Hungry");
317: when F_WEAK:
318: waddstr(cw, " Weak");
319: when F_FAINT:
320: waddstr(cw, " Fainting");
321: }
322: wclrtoeol(cw);
323: s_hungry = hungry_state;
324:
325: /*
326: * If nothing has changed since the last status, don't
327: * bother.
328: */
329: line_two:
330: if (!display &&
331: s_lvl == level &&
332: s_hp == stat_ptr->s_hpt &&
333: s_ac == ac_compute(FALSE) - dext_prot(s_dext) &&
334: s_pack == stat_ptr->s_pack &&
335: s_carry == stat_ptr->s_carry &&
336: s_exp == stat_ptr->s_exp ) return;
337:
338: if (!first_line) getyx(cw, oy, ox);
339: if (s_hp != max_ptr->s_hpt)
340: {
341: temp = s_hp = max_ptr->s_hpt;
342: for (hpwidth = 0; temp; hpwidth++)
343: temp /= 10;
344: }
345: sprintf(buf, "Lvl:%d Hp:%*d(%*d) Ac:%d Carry:%d(%d) Exp:%d/%lu %s",
346: level, hpwidth, stat_ptr->s_hpt, hpwidth, max_ptr->s_hpt,
347: ac_compute(FALSE) - dext_prot(s_dext),stat_ptr->s_pack/10,
348: stat_ptr->s_carry/10, stat_ptr->s_lvl, stat_ptr->s_exp,
349: cnames[player.t_ctype][min(stat_ptr->s_lvl-1, NUM_CNAMES-1)]);
350:
351: /*
352: * Save old status
353: */
354: s_lvl = level;
355: s_hp = stat_ptr->s_hpt;
356: s_ac = ac_compute(FALSE) - dext_prot(s_dext);
357: s_pack = stat_ptr->s_pack;
358: s_carry = stat_ptr->s_carry;
359: s_exp = stat_ptr->s_exp;
360: mvwaddstr(cw, lines - 1, 0, buf);
361: wclrtoeol(cw);
362: wmove(cw, oy, ox);
363: }
364:
365: /*
366: * wait_for
367: * Sit around until the guy types the right key
368: */
369: void
370: wait_for(char ch)
371: {
372: register char c;
373:
374: if (ch == '\n')
375: while ((c = wgetch(msgw)) != '\n' && c != '\r')
376: continue;
377: else
378: while (wgetch(msgw) != ch)
379: continue;
380: }
381:
382:
383: /*
384: * over_win:
385: * Given a current window, a new window, and the max y and x of the
386: * new window, paint the new window on top of the old window without
387: * destroying any of the old window. Current window and new window
388: * are assumed to have lines lines and cols columns (max y and max x
389: * pertain only the the useful information to be displayed.
390: * If redraw is non-zero, we wait for the character "redraw" to be
391: * typed and then redraw the starting screen.
392: */
393:
394: void
395: over_win(WINDOW *oldwin, WINDOW *newin, int maxy, int maxx, int cursory,
396: int cursorx, char redraw)
397: {
398: static char blanks[LINELEN+1];
399: register int line, i;
400: WINDOW *ow; /* Overlay window */
401:
402: /* Create a blanking line */
403: for (i=0; i<maxx && i<cols && i<LINELEN; i++) blanks[i] = ' ';
404: blanks[i] = '\0';
405:
406: /* Create the window we will display */
407: ow = newwin(lines, cols, 0, 0);
408:
409: /* Blank out the area we want to use */
410: if (oldwin == cw) {
411: msg("");
412: line = 1;
413: }
414: else line = 0;
415:
416: overwrite(oldwin, ow); /* Get a copy of the old window */
417:
418: /* Do the remaining blanking */
419: for (; line < maxy; line++) mvwaddstr(ow, line, 0, blanks);
420:
421: overlay(newin, ow); /* Overlay our new window */
422:
423: /* Move the cursor to the specified location */
424: wmove(ow, cursory, cursorx);
425:
426: clearok(ow, FALSE); /* Draw inventory without clearing */
427: draw(ow);
428:
429: if (redraw) {
430: wait_for(redraw);
431:
432: clearok(oldwin, FALSE); /* Setup to redraw current screen */
433: touchwin(oldwin); /* clearing first */
434: draw(oldwin);
435: }
436:
437: delwin(ow);
438: }
439:
440:
441: /*
442: * show_win:
443: * function used to display a window and wait before returning
444: */
445:
446: void
447: show_win(WINDOW *scr, char *message)
448: {
449: mvwaddstr(scr, 0, 0, message);
450: touchwin(scr);
451: wmove(scr, hero.y, hero.x);
452: draw(scr);
453: wait_for(' ');
454: clearok(cw, TRUE);
455: touchwin(cw);
456: }
457:
458: /*
459: * dbotline:
460: * Displays message on bottom line and waits for a space to return
461: */
462: void
463: dbotline(WINDOW *scr, char *message)
464: {
465: mvwaddstr(scr,lines-1,0,message);
466: draw(scr);
467: wait_for(' ');
468: }
469:
470:
471: /*
472: * restscr:
473: * Restores the screen to the terminal
474: */
475: void
476: restscr(WINDOW *scr)
477: {
478: clearok(scr,TRUE);
479: touchwin(scr);
480: }
481:
482: /*
483: * netread:
484: * Read a byte, short, or long machine independently
485: * Always returns the value as an unsigned long.
486: */
487:
488: unsigned long
489: netread(int *error, int size, FILE *stream)
490: {
491: unsigned long result = 0L, /* What we read in */
492: partial; /* Partial value */
493: int nextc, /* The next byte */
494: i; /* To index through the result a byte at a time */
495:
496: /* Be sure we have a right sized chunk */
497: if (size < 1 || size > 4) {
498: *error = 1;
499: return(0L);
500: }
501:
502: for (i=0; i<size; i++) {
503: nextc = getc(stream);
504: if (nextc == EOF) {
505: *error = 1;
506: return(0L);
507: }
508: else {
509: partial = (unsigned long) (nextc & 0xff);
510: partial <<= 8*i;
511: result |= partial;
512: }
513: }
514:
515: *error = 0;
516: return(result);
517: }
518:
519:
520:
521: /*
522: * netwrite:
523: * Write out a byte, short, or long machine independently.
524: * value: What to write
525: * size: How much to write out
526: * stream: Where to write it
527: */
528:
529: int
530: netwrite(unsigned long value, int size, FILE *stream)
531: {
532: int i; /* Goes through value one byte at a time */
533: char outc; /* The next character to be written */
534:
535: /* Be sure we have a right sized chunk */
536: if (size < 1 || size > 4) return(0);
537:
538: for (i=0; i<size; i++) {
539: outc = (char) ((value >> (8 * i)) & 0xff);
540: putc(outc, stream);
541: }
542: return(size);
543: }
CVSweb