comparison xrogue/io.c @ 133:e6179860cb76

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