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