comparison arogue7/io.c @ 125:adfa37e67084

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