Annotation of early-roguelike/rogue5/misc.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * All sorts of miscellaneous routines
3: *
4: * @(#)misc.c 4.66 (Berkeley) 08/06/83
5: *
6: * Rogue: Exploring the Dungeons of Doom
7: * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
8: * All rights reserved.
9: *
10: * See the file LICENSE.TXT for full copyright and licensing information.
11: */
12:
13: #include <stdlib.h>
14: #include <curses.h>
15: #include <string.h>
16: #include <ctype.h>
17: #include "rogue.h"
18:
19: /*
20: * look:
21: * A quick glance all around the player
22: */
23: #undef DEBUG
24:
25:
26: void
27: look(int wakeup)
28: {
29: int x, y;
30: chtype ch;
31: THING *tp;
32: PLACE *pp;
33: struct room *rp;
34: int ey, ex;
35: int passcount;
36: int pfl, *fp, pch;
37: int sy, sx, sumhero = 0, diffhero = 0;
38: # ifdef DEBUG
39: static int done = FALSE;
40:
41: if (done)
42: return;
43: done = TRUE;
44: # endif /* DEBUG */
45: passcount = 0;
46: rp = proom;
47: if (!ce(oldpos, hero))
48: {
49: erase_lamp(&oldpos, oldrp);
50: oldpos = hero;
51: oldrp = rp;
52: }
53: ey = hero.y + 1;
54: ex = hero.x + 1;
55: sx = hero.x - 1;
56: sy = hero.y - 1;
57: if (door_stop && !firstmove && running)
58: {
59: sumhero = hero.y + hero.x;
60: diffhero = hero.y - hero.x;
61: }
62: pp = INDEX(hero.y, hero.x);
63: pch = pp->p_ch;
64: pfl = pp->p_flags;
65:
66: for (y = sy; y <= ey; y++)
67: if (y > 0 && y < NUMLINES - 1) for (x = sx; x <= ex; x++)
68: {
69: if (x < 0 || x >= NUMCOLS)
70: continue;
71: if (!on(player, ISBLIND))
72: {
73: if (y == hero.y && x == hero.x)
74: continue;
75: }
76:
77: pp = INDEX(y, x);
78: ch = pp->p_ch;
79: if (ch == ' ') /* nothing need be done with a ' ' */
80: continue;
81: fp = &pp->p_flags;
82: if (pch != DOOR && ch != DOOR)
83: if ((pfl & F_PASS) != (*fp & F_PASS))
84: continue;
85: if (((*fp & F_PASS) || ch == DOOR) &&
86: ((pfl & F_PASS) || pch == DOOR))
87: {
88: if (hero.x != x && hero.y != y &&
89: !step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x)))
90: continue;
91: }
92:
93: if ((tp = pp->p_monst) == NULL)
94: ch = trip_ch(y, x, ch);
95: else
96: if (on(player, SEEMONST) && on(*tp, ISINVIS))
97: {
98: if (door_stop && !firstmove)
99: running = FALSE;
100: continue;
101: }
102: else
103: {
104: if (wakeup)
105: wake_monster(y, x);
106: if (see_monst(tp))
107: {
108: if (on(player, ISHALU))
109: ch = rnd(26) + 'A';
110: else
111: ch = tp->t_disguise;
112: }
113: }
114: if (on(player, ISBLIND) && (y != hero.y || x != hero.x))
115: continue;
116:
117: move(y, x);
118:
119: if ((proom->r_flags & ISDARK) && !see_floor && ch == FLOOR)
120: ch = ' ';
121:
122: if (tp != NULL || ch != CCHAR( inch() ))
123: addch(ch);
124:
125: if (door_stop && !firstmove && running)
126: {
127: switch (runch)
128: {
129: case 'h':
130: if (x == ex)
131: continue;
132: when 'j':
133: if (y == sy)
134: continue;
135: when 'k':
136: if (y == ey)
137: continue;
138: when 'l':
139: if (x == sx)
140: continue;
141: when 'y':
142: if ((y + x) - sumhero >= 1)
143: continue;
144: when 'u':
145: if ((y - x) - diffhero >= 1)
146: continue;
147: when 'n':
148: if ((y + x) - sumhero <= -1)
149: continue;
150: when 'b':
151: if ((y - x) - diffhero <= -1)
152: continue;
153: }
154: switch (ch)
155: {
156: case DOOR:
157: if (x == hero.x || y == hero.y)
158: running = FALSE;
159: break;
160: case PASSAGE:
161: if (x == hero.x || y == hero.y)
162: passcount++;
163: break;
164: case FLOOR:
165: case '|':
166: case '-':
167: case ' ':
168: break;
169: default:
170: running = FALSE;
171: break;
172: }
173: }
174: }
175: if (door_stop && !firstmove && passcount > 1)
176: running = FALSE;
177: if (!running || !jump)
178: mvaddch(hero.y, hero.x, PLAYER);
179: # ifdef DEBUG
180: done = FALSE;
181: # endif /* DEBUG */
182: }
183:
184: /*
185: * trip_ch:
186: * Return the character appropriate for this space, taking into
187: * account whether or not the player is tripping.
188: */
189: int
190: trip_ch(int y, int x, int ch)
191: {
192: if (on(player, ISHALU) && after)
193: switch (ch)
194: {
195: case FLOOR:
196: case ' ':
197: case PASSAGE:
198: case '-':
199: case '|':
200: case DOOR:
201: case TRAP:
202: break;
203: default:
204: if (y != stairs.y || x != stairs.x || !seenstairs)
205: ch = rnd_thing();
206: break;
207: }
208: return ch;
209: }
210:
211: /*
212: * erase_lamp:
213: * Erase the area shown by a lamp in a dark room.
214: */
215:
216: void
217: erase_lamp(const coord *pos, const struct room *rp)
218: {
219: int y, x, ey, sy, ex;
220:
221: if (!(see_floor && (rp->r_flags & (ISGONE|ISDARK)) == ISDARK
222: && !on(player,ISBLIND)))
223: return;
224:
225: ey = pos->y + 1;
226: ex = pos->x + 1;
227: sy = pos->y - 1;
228: for (x = pos->x - 1; x <= ex; x++)
229: for (y = sy; y <= ey; y++)
230: {
231: if (y == hero.y && x == hero.x)
232: continue;
233: move(y, x);
234: if (CCHAR( inch() ) == FLOOR)
235: addch(' ');
236: }
237: }
238:
239: /*
240: * show_floor:
241: * Should we show the floor in her room at this time?
242: */
243: int
244: show_floor(void)
245: {
246: if ((proom->r_flags & (ISGONE|ISDARK)) == ISDARK && !on(player, ISBLIND))
247: return see_floor;
248: else
249: return TRUE;
250: }
251:
252: /*
253: * find_obj:
254: * Find the unclaimed object at y, x
255: */
256: THING *
257: find_obj(int y, int x)
258: {
259: THING *obj;
260:
261: for (obj = lvl_obj; obj != NULL; obj = next(obj))
262: {
263: if (obj->o_pos.y == y && obj->o_pos.x == x)
264: return obj;
265: }
266: #ifdef MASTER
267: sprintf(prbuf, "Non-object %d,%d", y, x);
268: msg(prbuf);
269: return NULL;
270: #else
271: /* NOTREACHED */
272: return NULL;
273: #endif
274: }
275:
276: /*
277: * eat:
278: * She wants to eat something, so let her try
279: */
280:
281: void
282: eat(void)
283: {
284: THING *obj;
285:
286: if ((obj = get_item("eat", FOOD)) == NULL)
287: return;
288: if (obj->o_type != FOOD)
289: {
290: if (!terse)
291: msg("ugh, you would get ill if you ate that");
292: else
293: msg("that's Inedible!");
294: return;
295: }
296: if (food_left < 0)
297: food_left = 0;
298: if ((food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE)
299: food_left = STOMACHSIZE;
300: hungry_state = 0;
301: if (obj == cur_weapon)
302: cur_weapon = NULL;
303: if (obj->o_which == 1)
304: msg("my, that was a yummy %s", fruit);
305: else
306: if (rnd(100) > 70)
307: {
308: pstats.s_exp++;
309: msg("%s, this food tastes awful", choose_str("bummer", "yuk"));
310: check_level();
311: }
312: else
313: msg("%s, that tasted good", choose_str("oh, wow", "yum"));
314: leave_pack(obj, FALSE, FALSE);
315: }
316:
317: /*
318: * check_level:
319: * Check to see if the guy has gone up a level.
320: */
321:
322: void
323: check_level(void)
324: {
325: int i, add, olevel;
326:
327: for (i = 0; e_levels[i] != 0; i++)
328: if (e_levels[i] > pstats.s_exp)
329: break;
330: i++;
331: olevel = pstats.s_lvl;
332: pstats.s_lvl = i;
333: if (i > olevel)
334: {
335: add = roll(i - olevel, 10);
336: max_hp += add;
337: pstats.s_hpt += add;
338: msg("welcome to level %d", i);
339: }
340: }
341:
342: /*
343: * chg_str:
344: * used to modify the playes strength. It keeps track of the
345: * highest it has been, just in case
346: */
347:
348: void
349: chg_str(int amt)
350: {
351: int comp;
352:
353: if (amt == 0)
354: return;
355: add_str(&pstats.s_str, amt);
356: comp = pstats.s_str;
357: if (ISRING(LEFT, R_ADDSTR))
358: add_str(&comp, -cur_ring[LEFT]->o_arm);
359: if (ISRING(RIGHT, R_ADDSTR))
360: add_str(&comp, -cur_ring[RIGHT]->o_arm);
361: if (comp > max_stats.s_str)
362: max_stats.s_str = comp;
363: }
364:
365: /*
366: * add_str:
367: * Perform the actual add, checking upper and lower bound limits
368: */
369: void
370: add_str(int *sp, int amt)
371: {
372: if ((*sp += amt) < 3)
373: *sp = 3;
374: else if (*sp > 31)
375: *sp = 31;
376: }
377:
378: /*
379: * add_haste:
380: * Add a haste to the player
381: */
382: int
383: add_haste(int potion)
384: {
385: if (on(player, ISHASTE))
386: {
387: no_command += rnd(8);
388: player.t_flags &= ~(ISRUN|ISHASTE);
389: extinguish(nohaste);
390: msg("you faint from exhaustion");
391: return FALSE;
392: }
393: else
394: {
395: player.t_flags |= ISHASTE;
396: if (potion)
397: fuse(nohaste, 0, rnd(4)+4, AFTER);
398: return TRUE;
399: }
400: }
401:
402: /*
403: * aggravate:
404: * Aggravate all the monsters on this level
405: */
406:
407: void
408: aggravate(void)
409: {
410: THING *mp;
411:
412: for (mp = mlist; mp != NULL; mp = next(mp))
413: runto(&mp->t_pos);
414: }
415:
416: /*
417: * vowelstr:
418: * For printfs: if string starts with a vowel, return "n" for an
419: * "an".
420: */
421: char *
422: vowelstr(const char *str)
423: {
424: switch (*str)
425: {
426: case 'a': case 'A':
427: case 'e': case 'E':
428: case 'i': case 'I':
429: case 'o': case 'O':
430: case 'u': case 'U':
431: return "n";
432: default:
433: return "";
434: }
435: }
436:
437: /*
438: * is_current:
439: * See if the object is one of the currently used items
440: */
441: int
442: is_current(const THING *obj)
443: {
444: if (obj == NULL)
445: return FALSE;
446: if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
447: || obj == cur_ring[RIGHT])
448: {
449: if (!terse)
450: addmsg("That's already ");
451: msg("in use");
452: return TRUE;
453: }
454: return FALSE;
455: }
456:
457: /*
458: * get_dir:
459: * Set up the direction co_ordinate for use in varios "prefix"
460: * commands
461: */
462: int
463: get_dir(void)
464: {
465: char *prompt;
466: int gotit;
467: static coord last_delt= {0,0};
468:
469: if (again && last_dir != '\0')
470: {
471: delta.y = last_delt.y;
472: delta.x = last_delt.x;
473: dir_ch = last_dir;
474: }
475: else
476: {
477: if (!terse)
478: msg(prompt = "which direction? ");
479: else
480: prompt = "direction: ";
481: do
482: {
483: gotit = TRUE;
484: switch (dir_ch = readchar())
485: {
486: case 'h': case'H': delta.y = 0; delta.x = -1;
487: when 'j': case'J': delta.y = 1; delta.x = 0;
488: when 'k': case'K': delta.y = -1; delta.x = 0;
489: when 'l': case'L': delta.y = 0; delta.x = 1;
490: when 'y': case'Y': delta.y = -1; delta.x = -1;
491: when 'u': case'U': delta.y = -1; delta.x = 1;
492: when 'b': case'B': delta.y = 1; delta.x = -1;
493: when 'n': case'N': delta.y = 1; delta.x = 1;
494: when ESCAPE: last_dir = '\0'; reset_last(); msg(""); return FALSE;
495: otherwise:
496: mpos = 0;
497: msg(prompt);
498: gotit = FALSE;
499: }
500: } until (gotit);
501: if (isupper(dir_ch))
502: dir_ch = tolower(dir_ch);
503: last_dir = dir_ch;
504: last_delt.y = delta.y;
505: last_delt.x = delta.x;
506: }
507: if (on(player, ISHUH) && rnd(5) == 0)
508: do
509: {
510: delta.y = rnd(3) - 1;
511: delta.x = rnd(3) - 1;
512: } while (delta.y == 0 && delta.x == 0);
513: mpos = 0;
514: msg("");
515: return TRUE;
516: }
517:
518: /*
519: * sign:
520: * Return the sign of the number
521: */
522: int
523: sign(int nm)
524: {
525: if (nm < 0)
526: return -1;
527: else
528: return (nm > 0);
529: }
530:
531: /*
532: * spread:
533: * Give a spread around a given number (+/- 20%)
534: */
535: int
536: spread(int nm)
537: {
538: return nm - nm / 20 + rnd(nm / 10);
539: }
540:
541: /*
542: * call_it:
543: * Call an object something after use.
544: */
545:
546: void
547: call_it(struct obj_info *info)
548: {
549: if (info->oi_know)
550: {
551: if (info->oi_guess)
552: {
553: free(info->oi_guess);
554: info->oi_guess = NULL;
555: }
556: }
557: else if (!info->oi_guess)
558: {
559: msg(terse ? "call it: " : "what do you want to call it? ");
560: if (get_str(prbuf, stdscr) == NORM)
561: {
562: if (info->oi_guess != NULL)
563: free(info->oi_guess);
564: info->oi_guess = malloc(strlen(prbuf) + 1);
565: if (info->oi_guess != NULL)
566: strcpy(info->oi_guess, prbuf);
567: }
568: msg("");
569: }
570: }
571:
572: /*
573: * rnd_thing:
574: * Pick a random thing appropriate for this level
575: */
576: int
577: rnd_thing(void)
578: {
579: int i;
580: int thing_list[] = {
581: POTION, SCROLL, RING, STICK, FOOD, WEAPON, ARMOR, STAIRS, GOLD, AMULET
582: };
583:
584: if (level >= AMULETLEVEL)
585: i = rnd(sizeof thing_list / sizeof (int));
586: else
587: i = rnd(sizeof thing_list / sizeof (int) - 1);
588: return thing_list[i];
589: }
590:
591: /*
592: str str:
593: * Choose the first or second string depending on whether it the
594: * player is tripping
595: */
596: const char *
597: choose_str(const char *ts, const char *ns)
598: {
599: return (on(player, ISHALU) ? ts : ns);
600: }
CVSweb