Annotation of early-roguelike/rogue5/misc.c, Revision 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