Annotation of early-roguelike/urogue/monsters.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: monsters.c - File with various monster functions in it
! 3:
! 4: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
! 5: Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
! 6: All rights reserved.
! 7:
! 8: Based on "Advanced Rogue"
! 9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
! 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 <stdlib.h>
! 20: #include <string.h>
! 21: #include <ctype.h>
! 22: #include "rogue.h"
! 23:
! 24: /*
! 25: summon_monster()
! 26: Summon a monster.
! 27: */
! 28:
! 29: struct linked_list *
! 30: summon_monster(int type, int familiar, int print_message)
! 31: {
! 32: struct linked_list *mp;
! 33: struct thing *tp;
! 34: int monster;
! 35:
! 36: if (familiar && !is_wearing(R_WIZARD) && off(player, CANSUMMON))
! 37: {
! 38: msg("Only spellcasters can summon familiars!");
! 39: return(NULL);
! 40: }
! 41:
! 42: if (type == 0) /* Random monster modified by level */
! 43: {
! 44: int ndice = min(pstats.s_lvl, (nummonst - NUMSUMMON) / 8);
! 45:
! 46: monster = min(nummonst, roll(ndice, pstats.s_charisma));
! 47:
! 48: /*
! 49: * if a familiar exists, and it is higher in level, make it
! 50: * again
! 51: */
! 52:
! 53: if (fam_ptr != NULL)
! 54: {
! 55: struct thing *fp = THINGPTR(fam_ptr);
! 56:
! 57: monster = max(fp->t_index, monster);
! 58: }
! 59: }
! 60: else
! 61: monster = type;
! 62:
! 63: turn_on(player, SUMMONING);
! 64:
! 65: mp = creat_mons(&player, monster, NOMESSAGE);
! 66:
! 67: if (!mp)
! 68: {
! 69: msg("Summon failed.");
! 70: turn_off(player, SUMMONING);
! 71: return(NULL);
! 72: }
! 73:
! 74: if (print_message == MESSAGE)
! 75: {
! 76: msg("A %s appears out of nowhere!", monsters[monster].m_name);
! 77:
! 78: if (familiar)
! 79: msg("I am here to serve %s.", whoami);
! 80: else
! 81: {
! 82: msg("My goodness, are you Yendor?");
! 83: ++mons_summoned;
! 84: debug("%d monsters now summoned.", mons_summoned);
! 85: }
! 86: }
! 87:
! 88: tp = THINGPTR(mp);
! 89: turn_on(*tp, ISCHARMED); /* Summoned monsters are always charmed */
! 90:
! 91: if (familiar)
! 92: {
! 93: int i;
! 94: static const unsigned long fam_on[]= {ISREGEN,CANSHOOT,CANWIELD,HASARMOR,ISFAMILIAR,0};
! 95: static const unsigned long fam_off[]={ISMEAN, ISHUH, ISINVIS,
! 96: CANSURPRISE, NOMOVE,
! 97: ISSLOW, ISSHADOW, ISGREED, ISFAST,
! 98: CANFLY, ISFLEE, 0};
! 99:
! 100: for (i = 0; fam_on[i]; i++)
! 101: turn_on(*tp, fam_on[i]);
! 102:
! 103: for (i = 0; fam_off[i]; i++)
! 104: turn_off(*tp, fam_off[i]);
! 105:
! 106: if (fam_ptr != NULL) /* Get rid of old familiar */
! 107: {
! 108: struct thing *fp = THINGPTR(fam_ptr);
! 109: struct linked_list *fpack = fp->t_pack;
! 110: struct linked_list *item;
! 111:
! 112: if (fpack != NULL) /* Transfer pack */
! 113: {
! 114: if (tp->t_pack == NULL)
! 115: tp->t_pack = fpack;
! 116: else
! 117: {
! 118: for(item=tp->t_pack; item->l_next != NULL; item=next(item))
! 119: ; /* find last item in list */
! 120:
! 121: item->l_next = fpack;
! 122: fpack->l_prev = item;
! 123: }
! 124: }
! 125:
! 126: fpack = NULL;
! 127: killed(NULL, fam_ptr, NOMESSAGE, NOPOINTS);
! 128: }
! 129:
! 130: fam_ptr = mp;
! 131: fam_type = monster;
! 132:
! 133: /* improve their abilities a bit */
! 134:
! 135: tp->t_stats.s_hpt += roll(2, pstats.s_lvl);
! 136: tp->t_stats.s_lvl += roll(2, (pstats.s_lvl / 4) + 1);
! 137: tp->t_stats.s_arm -= roll(2, (pstats.s_lvl / 4) + 1);
! 138: tp->t_stats.s_str += roll(2, (pstats.s_lvl / 4) + 1);
! 139: tp->t_stats.s_intel += roll(2, (pstats.s_lvl / 4) + 1);
! 140: tp->t_stats.s_wisdom += roll(2, (pstats.s_lvl / 4) + 1);
! 141: tp->t_stats.s_dext += roll(2, (pstats.s_lvl / 4) + 1);
! 142: tp->t_stats.s_const += roll(2, (pstats.s_lvl / 4) + 1);
! 143: tp->t_stats.s_charisma += roll(2, (pstats.s_lvl / 4) + 1);
! 144:
! 145: /* some monsters do no damage by default */
! 146:
! 147: if (strcmp(tp->t_stats.s_dmg, "0d0") == 0)
! 148: tp->t_stats.s_dmg = "1d8";
! 149:
! 150: tp->maxstats = tp->t_stats; /* structure assignment */
! 151: }
! 152:
! 153: turn_off(player, SUMMONING);
! 154:
! 155: return(mp);
! 156: }
! 157:
! 158: /*
! 159: randmonster()
! 160: wander - wandering monster allowed
! 161: grab - a throne room monster allowed
! 162: */
! 163:
! 164: int
! 165: randmonster(int wander, int grab)
! 166: {
! 167: int mons_number, cur_level, range, i;
! 168:
! 169: /* Do we want a merchant? */
! 170:
! 171: if (wander == WANDER && monsters[nummonst].m_wander && rnd(5000) < 3)
! 172: return(nummonst);
! 173:
! 174: cur_level = level;
! 175: range = 4 * NLEVMONS;
! 176: i = 0;
! 177:
! 178: do
! 179: {
! 180: if (i++ > range * 10) /* just in case all have be genocided */
! 181: {
! 182: i = 0;
! 183:
! 184: if (--cur_level <= 0)
! 185: fatal("Rogue could not find a monster to make");
! 186: }
! 187:
! 188: mons_number = NLEVMONS * (cur_level - 1) +
! 189: (rnd(range) - (range - 1 - NLEVMONS));
! 190:
! 191: if (mons_number < 1)
! 192: mons_number = rnd(NLEVMONS) + 1;
! 193: else if (mons_number > nummonst - NUMSUMMON - 1)
! 194: {
! 195: if (grab == GRAB)
! 196: mons_number = rnd(range + NUMSUMMON) +
! 197: (nummonst - 1) -
! 198: (range + NUMSUMMON - 1);
! 199: else if (mons_number > nummonst - 1)
! 200: mons_number = rnd(range) +
! 201: (nummonst - NUMSUMMON - 1) -
! 202: (range - 1);
! 203: }
! 204: }
! 205: while (wander == WANDER ? !monsters[mons_number].m_wander ||
! 206: !monsters[mons_number].m_normal :
! 207: !monsters[mons_number].m_normal);
! 208:
! 209: return((short)mons_number);
! 210: }
! 211:
! 212: /*
! 213: new_monster()
! 214: Pick a new monster and add it to the list
! 215: */
! 216:
! 217: void
! 218: new_monster(struct linked_list *item, int type, coord *cp, int max_monster)
! 219: {
! 220: struct thing *tp;
! 221: struct monster *mp;
! 222: char *ip, *hitp;
! 223: int i, min_intel, max_intel;
! 224: int num_dice, num_sides = 8, num_extra = 0;
! 225: int eff_charisma = pstats.s_charisma;
! 226: int eff_intel = pstats.s_intel;
! 227:
! 228: attach(mlist, item);
! 229: tp = THINGPTR(item);
! 230: tp->t_index = type;
! 231: tp->t_wasshot = FALSE;
! 232: tp->t_type = monsters[type].m_appear;
! 233: tp->t_ctype = C_MONSTER;
! 234: tp->t_no_move = 0;
! 235: tp->t_doorgoal = -1;
! 236: tp->t_pos = *cp;
! 237: tp->t_oldpos = *cp;
! 238: tp->t_oldch = CCHAR( mvwinch(cw, cp->y, cp->x) );
! 239: mvwaddch(mw, cp->y, cp->x, tp->t_type);
! 240: mp = &monsters[tp->t_index];
! 241:
! 242: /* Figure out monster's hit points */
! 243:
! 244: hitp = mp->m_stats.s_hpt;
! 245: num_dice = atoi(hitp);
! 246:
! 247: if ((hitp = strchr(hitp, 'd')) != NULL)
! 248: {
! 249: num_sides = atoi(++hitp);
! 250:
! 251: if ((hitp = strchr(hitp, '+')) != NULL)
! 252: num_extra = atoi(++hitp);
! 253: }
! 254:
! 255: if (max_monster == MAXSTATS)
! 256: tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
! 257: else
! 258: tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;
! 259:
! 260: tp->t_stats.s_lvl = mp->m_stats.s_lvl;
! 261: tp->t_stats.s_arm = mp->m_stats.s_arm;
! 262: tp->t_stats.s_dmg = mp->m_stats.s_dmg;
! 263: tp->t_stats.s_exp = mp->m_stats.s_exp + mp->m_add_exp * tp->t_stats.s_hpt;
! 264: tp->t_stats.s_str = mp->m_stats.s_str;
! 265:
! 266: if (max_level > 30)
! 267: {
! 268: tp->t_stats.s_hpt += roll(4, (max_level - 60) * 2);
! 269: tp->t_stats.s_lvl += roll(4, (max_level - 60) / 8);
! 270: tp->t_stats.s_arm -= roll(2, (max_level - 60) / 8);
! 271: tp->t_stats.s_str += roll(2, (max_level - 60) / 12);
! 272: tp->t_stats.s_exp += roll(4, (max_level - 60) * 2) * mp->m_add_exp;
! 273: }
! 274:
! 275: /*
! 276: * just initailize others values to something reasonable for now
! 277: * maybe someday will *really* put these in monster table
! 278: */
! 279:
! 280: tp->t_stats.s_wisdom = 8 + rnd(4);
! 281: tp->t_stats.s_dext = 8 + rnd(4);
! 282: tp->t_stats.s_const = 8 + rnd(4);
! 283: tp->t_stats.s_charisma = 8 + rnd(4);
! 284:
! 285: if (max_level > 45)
! 286: tp->t_stats.s_dext += roll(2, (max_level - 50) / 8);
! 287:
! 288: /* Set the initial flags */
! 289:
! 290: for (i = 0; i < 16; i++)
! 291: tp->t_flags[i] = 0;
! 292:
! 293: for (i = 0; i < 16; i++)
! 294: turn_on(*tp, mp->m_flags[i]);
! 295:
! 296: /* suprising monsters don't always surprise you */
! 297:
! 298: if (!max_monster && on(*tp, CANSURPRISE) && rnd(100) < 20)
! 299: turn_off(*tp, CANSURPRISE);
! 300:
! 301: /* If this monster is unique, genocide it */
! 302:
! 303: if (on(*tp, ISUNIQUE))
! 304: mp->m_normal = FALSE;
! 305:
! 306: /* gods automatically get special abilities */
! 307:
! 308: if (on(*tp, ISGOD))
! 309: {
! 310: turn_on(*tp, CANFRIGHTEN);
! 311: turn_on(*tp, CANCAST);
! 312: turn_on(*tp, CANFLY);
! 313: turn_on(*tp, CANBARGAIN);
! 314: turn_on(*tp, ISLARGE);
! 315: turn_on(*tp, CANTELEPORT);
! 316: turn_on(*tp, CANSPEAK);
! 317: turn_on(*tp, CANDARKEN);
! 318: turn_on(*tp, CANSEE);
! 319: turn_on(*tp, CANLIGHT);
! 320: turn_on(*tp, BMAGICHIT);
! 321: }
! 322:
! 323: tp->t_turn = TRUE;
! 324: tp->t_pack = NULL;
! 325:
! 326: /* Figure intelligence */
! 327:
! 328: min_intel = atoi(mp->m_intel);
! 329:
! 330: if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
! 331: tp->t_stats.s_intel = min_intel;
! 332: else
! 333: {
! 334: max_intel = atoi(++ip);
! 335:
! 336: if (max_monster)
! 337: tp->t_stats.s_intel = max_intel;
! 338: else
! 339: tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
! 340: }
! 341:
! 342: tp->t_stats.s_power = (rnd(tp->t_stats.s_lvl / 5) + 1) * tp->t_stats.s_intel;
! 343:
! 344: tp->maxstats = tp->t_stats; /* structure assignment */
! 345:
! 346: /* If the monster can shoot, it may have a weapon */
! 347:
! 348: if (on(*tp, CANSHOOT) && (max_monster || rnd(9) < 6))
! 349: {
! 350: struct linked_list *thrower_item, *missile_item;
! 351: struct object *thrower, *a_missile;
! 352:
! 353: thrower_item = new_item(sizeof *thrower);
! 354: thrower = OBJPTR(thrower_item);
! 355: carried_weapon(tp, thrower);
! 356:
! 357: missile_item = new_item(sizeof *a_missile);
! 358: a_missile = OBJPTR(missile_item);
! 359: carried_weapon(tp, a_missile);
! 360:
! 361: /* The monster may use a crossbow, sling, footbow, or an arrow */
! 362: /* Take racial preferences into account */
! 363:
! 364: if ((strcmp(mp->m_name, "elf") == 0) ||
! 365: (strcmp(mp->m_name, "noldor elf") == 0))
! 366: {
! 367: thrower->o_which = BOW;
! 368:
! 369: if (rnd(5) == 0)
! 370: a_missile->o_which = SILVERARROW;
! 371: else
! 372: a_missile->o_which = ARROW;
! 373: }
! 374: else if ((strcmp(mp->m_name, "dwarf") == 0) ||
! 375: (strcmp(mp->m_name, "kazad dwarf") == 0))
! 376: {
! 377: thrower->o_which = CROSSBOW;
! 378: a_missile->o_which = BOLT;
! 379: }
! 380: else if (on(*tp, ISSMALL))
! 381: {
! 382: switch (rnd(3))
! 383: {
! 384: case 0:
! 385: thrower->o_which = SLING;
! 386: a_missile->o_which = BULLET;
! 387: break;
! 388: default:
! 389: thrower->o_which = SLING;
! 390: a_missile->o_which = ROCK;
! 391: }
! 392: }
! 393: else if (on(*tp, ISLARGE))
! 394: {
! 395: switch (rnd(4))
! 396: {
! 397: case 0:
! 398: thrower->o_which = CROSSBOW;
! 399: a_missile->o_which = BOLT;
! 400: break;
! 401:
! 402: case 1:
! 403: thrower->o_which = FOOTBOW;
! 404: a_missile->o_which = FBBOLT;
! 405: break;
! 406:
! 407: default:
! 408: thrower->o_which = BOW;
! 409:
! 410: if (rnd(5) == 0)
! 411: a_missile->o_which = FLAMEARROW;
! 412: else
! 413: a_missile->o_which = ARROW;
! 414:
! 415: break;
! 416: }
! 417: }
! 418: else
! 419: {
! 420: switch (rnd(6))
! 421: {
! 422: case 1:
! 423: thrower->o_which = SLING;
! 424: a_missile->o_which = ROCK;
! 425: break;
! 426:
! 427: case 2:
! 428: thrower->o_which = CROSSBOW;
! 429: a_missile->o_which = BOLT;
! 430: break;
! 431:
! 432: case 3:
! 433: thrower->o_which = FOOTBOW;
! 434: a_missile->o_which = FBBOLT;
! 435: break;
! 436:
! 437: case 4:
! 438: thrower->o_which = BOW;
! 439: a_missile->o_which = ARROW;
! 440: break;
! 441:
! 442: default:
! 443: thrower->o_which = SLING;
! 444: a_missile->o_which = BULLET;
! 445: break;
! 446: }
! 447: }
! 448:
! 449: init_weapon(thrower, thrower->o_which);
! 450: init_weapon(a_missile, a_missile->o_which);
! 451:
! 452: attach(tp->t_pack, thrower_item);
! 453: attach(tp->t_pack, missile_item);
! 454: }
! 455:
! 456: /* monsters that wield weapons */
! 457:
! 458: if (on(*tp, CANWIELD))
! 459: {
! 460: if (max_monster || rnd(3))
! 461: {
! 462: struct linked_list *wield_item;
! 463: struct object *wielded;
! 464:
! 465: wield_item = new_item(sizeof *wielded);
! 466: wielded = OBJPTR(wield_item);
! 467: carried_weapon(tp, wielded);
! 468:
! 469: i = rnd(CLAYMORE - CLUB) + rnd(2 * tp->t_stats.s_lvl);
! 470: i = min(i, CLAYMORE);
! 471: wielded->o_which = i;
! 472: init_weapon(wielded, wielded->o_which);
! 473:
! 474: /* Is it too heavy? */
! 475:
! 476: if (itemweight(wielded) > 8 * tp->t_stats.s_str)
! 477: discard(wield_item);
! 478: else
! 479: attach(tp->t_pack, wield_item);
! 480: }
! 481: }
! 482:
! 483: if (is_wearing(R_AGGR))
! 484: chase_it(cp, &player);
! 485: else
! 486: {
! 487: turn_off(*tp, ISRUN);
! 488:
! 489: if (on(*tp, ISFLEE) && (rnd(4) == 0))
! 490: turn_off(*tp, ISFLEE);
! 491:
! 492: if (rnd(luck) == 0)
! 493: switch (player.t_ctype)
! 494: {
! 495: case C_MAGICIAN:
! 496: case C_ILLUSION:
! 497: eff_intel = 2 * pstats.s_intel;
! 498: break;
! 499: case C_DRUID:
! 500: eff_intel = 2 * pstats.s_intel;
! 501: case C_RANGER:
! 502: eff_charisma = 2 * pstats.s_charisma;
! 503: break;
! 504: case C_ASSASIN:
! 505: case C_THIEF:
! 506: case C_NINJA:
! 507: eff_charisma = pstats.s_charisma / 2;
! 508: break;
! 509: }
! 510:
! 511: /* LOWFRIENDLY monsters might be friendly */
! 512:
! 513: i = roll(1,100);
! 514:
! 515: if (i == 0 || (on(*tp, LOWFRIENDLY) && i < eff_charisma) ||
! 516: (on(*tp, MEDFRIENDLY) && i < 3 * eff_charisma) ||
! 517: (on(*tp, HIGHFRIENDLY) && i < 5 * eff_charisma))
! 518: {
! 519: turn_on(*tp, ISFRIENDLY);
! 520: turn_off(*tp, ISMEAN);
! 521: }
! 522:
! 523: i = roll(1,100);
! 524:
! 525: if (i == 0 || (on(*tp, LOWCAST) && i < eff_intel) ||
! 526: (on(*tp, MEDCAST) && i < 3 * eff_intel) ||
! 527: (on(*tp, HIGHCAST) && i < 5 * eff_intel))
! 528: {
! 529: turn_on(*tp, CANCAST);
! 530: }
! 531:
! 532: if (on(*tp, ISDISGUISE))
! 533: {
! 534: char mch = 0;
! 535:
! 536: if (tp->t_pack != NULL)
! 537: mch = (OBJPTR(tp->t_pack))->o_type;
! 538: else
! 539: switch (rnd(level > arts[0].ar_level ? 10 : 9))
! 540: {
! 541: case 0: mch = GOLD; break;
! 542: case 1: mch = POTION; break;
! 543: case 2: mch = SCROLL; break;
! 544: case 3: mch = FOOD; break;
! 545: case 4: mch = WEAPON; break;
! 546: case 5: mch = ARMOR; break;
! 547: case 6: mch = RING; break;
! 548: case 7: mch = STICK; break;
! 549: case 8: mch = monsters[randmonster(NOWANDER, NOGRAB)].m_appear;
! 550: break;
! 551: case 9: mch = ARTIFACT; break;
! 552: }
! 553:
! 554: tp->t_disguise = mch;
! 555: }
! 556: }
! 557: }
! 558:
! 559: /*
! 560: wanderer()
! 561: A wandering monster has awakened and is headed for the player
! 562: */
! 563:
! 564: void
! 565: wanderer(void)
! 566: {
! 567: int i, cnt = 0;
! 568: struct room *hr = roomin(hero);
! 569: struct linked_list *item;
! 570: struct thing *tp;
! 571: coord cp;
! 572: char *loc;
! 573: int which;
! 574:
! 575: /* Find a place for it -- avoid the player's room */
! 576:
! 577: do
! 578: {
! 579: do
! 580: {
! 581: cnt++;
! 582: i = rnd_room();
! 583: }
! 584: while (!(hr != &rooms[i] || levtype == MAZELEV
! 585: || levtype == THRONE || cnt > 5000));
! 586:
! 587: rnd_pos(&rooms[i], &cp);
! 588: }
! 589: while(!step_ok(cp.y, cp.x, NOMONST, NULL));
! 590:
! 591: /* Create a new wandering monster */
! 592:
! 593: item = new_item(sizeof *tp);
! 594: which = randmonster(TRUE, FALSE);
! 595: new_monster(item, which, &cp, FALSE);
! 596:
! 597: tp = THINGPTR(item);
! 598: tp->t_pos = cp; /* Assign the position to the monster */
! 599:
! 600: chase_it(&tp->t_pos, &player);
! 601:
! 602: i = rnd(7);
! 603:
! 604: if (on(*tp, ISSWARM) && i < 5)
! 605: cnt = roll(2, 4);
! 606: else if (on(*tp, ISFLOCK) && i < 5)
! 607: cnt = roll(1, 4);
! 608: else
! 609: cnt = 0;
! 610:
! 611: for (i = 1; i <= cnt; i++)
! 612: {
! 613: struct linked_list *ip = creat_mons(tp, which, NOMESSAGE);
! 614:
! 615: if (ip != NULL)
! 616: {
! 617: struct thing *mp = THINGPTR(ip);
! 618:
! 619: if (on(*tp, ISFRIENDLY))
! 620: turn_on(*mp, ISFRIENDLY);
! 621: else
! 622: turn_off(*mp, ISFRIENDLY);
! 623: }
! 624: }
! 625:
! 626: if (cnt > 0)
! 627: {
! 628: if (on(*tp, LOWCAST) || on(*tp, MEDCAST) || on(*tp, HIGHCAST))
! 629: turn_on(*tp, CANCAST);
! 630:
! 631: tp->t_stats.s_hpt += roll(2, 8);
! 632: tp->t_stats.s_lvl += roll(2, 3);
! 633: tp->t_stats.s_arm -= roll(1, 6);
! 634: tp->t_stats.s_str += roll(2, 3);
! 635: tp->t_stats.s_intel += roll(2, 3);
! 636: tp->t_stats.s_exp += roll(2, 8) * monsters[which].m_add_exp;
! 637: }
! 638:
! 639: i = DISTANCE(cp, hero);
! 640:
! 641: if (i < 20)
! 642: loc = "very close to you";
! 643: else if (i < 400)
! 644: loc = "nearby";
! 645: else
! 646: loc = "in the distance";
! 647:
! 648: if (wizard)
! 649: msg("Started a wandering %s.", monsters[tp->t_index].m_name);
! 650: else if (on(*tp, ISUNDEAD) && (player.t_ctype == C_CLERIC ||
! 651: player.t_ctype == C_PALADIN || is_wearing(R_PIETY)))
! 652: msg("You sense a new ungodly monster %s.", loc);
! 653: else if (on(player, CANHEAR) || (player.t_ctype == C_THIEF &&
! 654: rnd(20) == 0))
! 655: msg("You hear a new %s moving %s.",
! 656: monsters[tp->t_index].m_name, loc);
! 657: else if (on(player, CANSCENT) || (player.t_ctype == C_THIEF &&
! 658: rnd(20) == 0))
! 659: msg("You smell a new %s %s.", monsters[tp->t_index].m_name,
! 660: loc);
! 661: }
! 662:
! 663: /*
! 664: wake_monster
! 665:
! 666: what to do when the hero steps next to a monster
! 667: */
! 668:
! 669: struct linked_list *
! 670: wake_monster(int y, int x)
! 671: {
! 672: struct thing *tp;
! 673: struct linked_list *it;
! 674: struct room *trp;
! 675: char *mname;
! 676:
! 677: if ((it = find_mons(y, x)) == NULL)
! 678: {
! 679: debug("Can't find monster in show.");
! 680: return(NULL);
! 681: }
! 682:
! 683: tp = THINGPTR(it);
! 684:
! 685: if ((good_monster(*tp)) || on(player, SUMMONING))
! 686: {
! 687: chase_it(&tp->t_pos, &player);
! 688: turn_off(*tp, ISINVIS);
! 689: turn_off(*tp, CANSURPRISE);
! 690: return(it);
! 691: }
! 692:
! 693: trp = roomin(tp->t_pos); /* Current room for monster */
! 694: mname = monsters[tp->t_index].m_name;
! 695:
! 696: /* Let greedy ones guard gold */
! 697:
! 698: if (on(*tp, ISGREED) && off(*tp, ISRUN))
! 699: if ((trp != NULL) && (lvl_obj != NULL))
! 700: {
! 701: struct linked_list *item;
! 702: struct object *cur;
! 703:
! 704: for (item = lvl_obj; item != NULL; item = next(item))
! 705: {
! 706: cur = OBJPTR(item);
! 707:
! 708: if ((cur->o_type == GOLD) &&
! 709: (roomin(cur->o_pos) == trp))
! 710: {
! 711: /* Run to the gold */
! 712: tp->t_horde = cur;
! 713: turn_on(*tp, ISRUN);
! 714: turn_off(*tp, ISDISGUISE);
! 715: tp->t_ischasing = FALSE;
! 716: /* Make it worth protecting */
! 717: cur->o_count += roll(2, 3) * GOLDCALC;
! 718: break;
! 719: }
! 720: }
! 721: }
! 722:
! 723: /*
! 724: * Every time he sees mean monster, it might start chasing him unique
! 725: * monsters always do
! 726: */
! 727:
! 728: if ( (on(*tp, ISUNIQUE)) ||
! 729: ( (rnd(100) > 33) &&
! 730: on(*tp, ISMEAN) &&
! 731: off(*tp, ISHELD) &&
! 732: off(*tp, ISRUN) &&
! 733: !is_stealth(&player) &&
! 734: (off(player, ISINVIS) || on(*tp, CANSEE))
! 735: )
! 736: )
! 737: {
! 738: chase_it(&tp->t_pos, &player);
! 739: }
! 740:
! 741: /* Handle gaze attacks */
! 742:
! 743: if (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x) &&
! 744: off(player, ISINVIS))
! 745: {
! 746: if (on(*tp, CANHUH)) /* Confusion */
! 747: {
! 748: if (on(player, CANREFLECT))
! 749: {
! 750: msg("You reflect the bewildering stare of the %s.", mname);
! 751:
! 752: if (save_throw(VS_MAGIC, tp))
! 753: {
! 754: msg("The %s is confused!", mname);
! 755: turn_on(*tp, ISHUH);
! 756: }
! 757: else
! 758: msg("The %s staggers for a moment.", mname);
! 759: }
! 760: else if (save(VS_MAGIC))
! 761: {
! 762: msg("You feel dizzy for a moment, but it quickly passes.");
! 763:
! 764: if (rnd(100) < 67)
! 765: turn_off(*tp, CANHUH);
! 766: }
! 767: else if (off(player, ISCLEAR))
! 768: {
! 769: if (off(player, ISHUH))
! 770: {
! 771: light_fuse(FUSE_UNCONFUSE, 0, rnd(20) + HUHDURATION, AFTER);
! 772: msg("The %s's gaze has confused you.", mname);
! 773: turn_on(player, ISHUH);
! 774: }
! 775: else
! 776: lengthen_fuse(FUSE_UNCONFUSE, rnd(20) + HUHDURATION);
! 777: }
! 778: }
! 779:
! 780: if (on(*tp, CANSNORE)) /* Sleep */
! 781: {
! 782: if (on(player, CANREFLECT))
! 783: {
! 784: msg("You reflect the lethargic glance of the %s", mname);
! 785:
! 786: if (save_throw(VS_PARALYZATION, tp))
! 787: {
! 788: msg("The %s falls asleep!", mname);
! 789: tp->t_no_move += SLEEPTIME;
! 790: }
! 791: }
! 792: else if (no_command == 0 && !save(VS_PARALYZATION))
! 793: {
! 794: if (is_wearing(R_ALERT))
! 795: msg("You feel slightly drowsy for a moment.");
! 796: else
! 797: {
! 798: msg("The %s's gaze puts you to sleep.", mname);
! 799: no_command = SLEEPTIME;
! 800:
! 801: if (rnd(100) < 50)
! 802: turn_off(*tp, CANSNORE);
! 803: }
! 804: }
! 805: }
! 806:
! 807: if (on(*tp, CANFRIGHTEN)) /* Fear */
! 808: {
! 809: turn_off(*tp, CANFRIGHTEN);
! 810:
! 811: if (on(player, CANREFLECT))
! 812: {
! 813: msg("The %s sees its reflection. ", mname);
! 814:
! 815: if (save_throw(VS_MAGIC,tp))
! 816: {
! 817: msg("The %s is terrified by its reflection!", mname);
! 818: turn_on(*tp, ISFLEE);
! 819: }
! 820: }
! 821: else
! 822: {
! 823: if (!save(VS_WAND) && !(on(player, ISFLEE) &&
! 824: (player.t_chasee==tp)))
! 825: {
! 826: if ((player.t_ctype != C_PALADIN) &&
! 827: off(player, SUPERHERO))
! 828: {
! 829: turn_on(player, ISFLEE);
! 830: player.t_ischasing = FALSE;
! 831: player.t_chasee = tp;
! 832: msg("The sight of the %s terrifies you.", mname);
! 833: }
! 834: else
! 835: msg("My, the %s looks ugly.", mname);
! 836: }
! 837: }
! 838: }
! 839:
! 840: if (on(*tp, LOOKSLOW)) /* Slow */
! 841: {
! 842: turn_off(*tp, LOOKSLOW);
! 843:
! 844: if (on(player, CANREFLECT))
! 845: {
! 846: msg("You reflect the mournful glare of the %s.", mname);
! 847:
! 848: if (save_throw(VS_MAGIC,tp))
! 849: {
! 850: msg("The %s is slowing down!", mname);
! 851: turn_on(*tp, ISSLOW);
! 852: }
! 853: }
! 854: else if (is_wearing(R_FREEDOM) || save(VS_MAGIC))
! 855: msg("You feel run-down for a moment.");
! 856: else
! 857: {
! 858: if (on(player, ISHASTE)) /* Already sped up */
! 859: {
! 860: extinguish_fuse(FUSE_NOHASTE);
! 861: nohaste(NULL);
! 862: }
! 863: else
! 864: {
! 865: msg("You feel yourself moving %sslower.",
! 866: on(player, ISSLOW) ? "even " : "");
! 867:
! 868: if (on(player, ISSLOW))
! 869: lengthen_fuse(FUSE_NOSLOW, rnd(4) + 4);
! 870: else
! 871: {
! 872: turn_on(player, ISSLOW);
! 873: player.t_turn = TRUE;
! 874: light_fuse(FUSE_NOSLOW, 0, rnd(4) + 4, AFTER);
! 875: }
! 876: }
! 877: }
! 878: }
! 879:
! 880: if (on(*tp, CANBLIND)) /* Blinding */
! 881: {
! 882: turn_off(*tp, CANBLIND);
! 883:
! 884: if (on(player, CANREFLECT))
! 885: {
! 886: msg("You reflect the blinding stare of the %s.", mname);
! 887:
! 888: if (save_throw(VS_WAND, tp))
! 889: {
! 890: msg("The %s is blinded!", mname);
! 891: turn_on(*tp, ISHUH);
! 892: }
! 893: }
! 894: else if (off(player, ISBLIND))
! 895: if (save(VS_WAND) || is_wearing(R_TRUESEE) || is_wearing(R_SEEINVIS))
! 896: msg("Your eyes film over for a moment.");
! 897: else
! 898: {
! 899: msg("The gaze of the %s blinds you.", mname);
! 900: turn_on(player, ISBLIND);
! 901: light_fuse(FUSE_SIGHT, 0, rnd(30) + 20, AFTER);
! 902: look(FALSE);
! 903: }
! 904: }
! 905:
! 906: if (on(*tp, LOOKSTONE)) /* Stoning */
! 907: {
! 908: turn_off(*tp, LOOKSTONE);
! 909:
! 910: if (on(player, CANREFLECT))
! 911: {
! 912: msg("You reflect the flinty look of the %s.", mname);
! 913:
! 914: if (save_throw(VS_PETRIFICATION,tp))
! 915: {
! 916: msg("The %s suddenly stiffens", mname);
! 917: tp->t_no_move += STONETIME;
! 918: }
! 919: else
! 920: {
! 921: msg("The %s is turned to stone!", mname);
! 922: killed(&player, it, NOMESSAGE, POINTS);
! 923: }
! 924: }
! 925: else
! 926: {
! 927: if (on(player, CANINWALL))
! 928: msg("The %s cannot focus on you.", mname);
! 929: else
! 930: {
! 931: msg("The gaze of the %s stiffens your limbs.", mname);
! 932:
! 933: if (save(VS_PETRIFICATION))
! 934: no_command = STONETIME;
! 935: else if (rnd(100))
! 936: no_command = STONETIME * 3;
! 937: else
! 938: {
! 939: msg("The gaze of the %s petrifies you.", mname);
! 940: msg("You are turned to stone!!! --More--");
! 941: wait_for(' ');
! 942: death(D_PETRIFY);
! 943: return(it);
! 944: }
! 945: }
! 946: }
! 947: }
! 948: }
! 949:
! 950: /*
! 951: * True Sight sees all Never see ISINWALL or CANSURPRISE See ISSHADOW
! 952: * 80% See ISINVIS with See Invisibilty
! 953: */
! 954:
! 955: if (off(player, CANTRUESEE) &&
! 956: on(*tp, ISINWALL) || on(*tp, CANSURPRISE) ||
! 957: (on(*tp, ISSHADOW) && rnd(100) < 80) ||
! 958: (on(*tp, ISINVIS) && off(player, CANSEE)))
! 959: {
! 960: /*
! 961: TODO: incomplete - need to finish logic
! 962: int ch = mvwinch(stdscr, y, x);
! 963: */
! 964: }
! 965:
! 966:
! 967: /* hero might be able to hear or smell monster if he can't see it */
! 968:
! 969: if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 ||
! 970: on(player, CANHEAR)) && !cansee(tp->t_pos.y, tp->t_pos.x))
! 971: msg("You hear a %s nearby.", mname);
! 972: else if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 ||
! 973: on(player, CANSCENT)) && !cansee(tp->t_pos.y, tp->t_pos.x))
! 974: msg("You smell a %s nearby.", mname);
! 975:
! 976: return(it);
! 977: }
! 978:
! 979: /*
! 980: genocide()
! 981: wipe out hated monsters flags: ISBLESSED, ISCURSED
! 982: */
! 983:
! 984: void
! 985: genocide(int flags)
! 986: {
! 987: struct linked_list *ip;
! 988: struct thing *mp;
! 989: struct linked_list *nip;
! 990: int which_monst;
! 991: int blessed = flags & ISBLESSED;
! 992: int cursed = flags & ISCURSED;
! 993:
! 994: while ((which_monst = get_monster_number("genocide")) == 0)
! 995: ;
! 996:
! 997: if (cursed) /* oops... */
! 998: {
! 999: new_level(THRONE, which_monst);
! 1000: msg("What's this I hear about you trying to wipe me out?");
! 1001: fighting = running = after = FALSE;
! 1002: return;
! 1003: }
! 1004:
! 1005: /* Remove this monster from the present level */
! 1006:
! 1007: for (ip = mlist; ip; ip = nip)
! 1008: {
! 1009: mp = THINGPTR(ip);
! 1010: nip = next(ip);
! 1011:
! 1012: if (mp->t_index == which_monst)
! 1013: {
! 1014: check_residue(mp); /* Check for special features before removing */
! 1015: remove_monster(&mp->t_pos, ip);
! 1016: }
! 1017: }
! 1018:
! 1019: /* Remove from available monsters */
! 1020:
! 1021: monsters[which_monst].m_normal = FALSE;
! 1022: monsters[which_monst].m_wander = FALSE;
! 1023: mpos = 0;
! 1024: msg("You have wiped out the %s.", monsters[which_monst].m_name);
! 1025:
! 1026: if (blessed)
! 1027: genocide(ISNORMAL);
! 1028: }
! 1029:
! 1030:
! 1031: /*
! 1032: id_monst()
! 1033: lists the monsters with the displayed by the character unless
! 1034: there is only one in which case it is returned as the string
! 1035: */
! 1036:
! 1037: void
! 1038: id_monst(int monster)
! 1039: {
! 1040: int i;
! 1041:
! 1042: for (i = 1; i <= nummonst + 2; i++)
! 1043: if (monsters[i].m_appear == monster)
! 1044: add_line("A %s ", monsters[i].m_name);
! 1045:
! 1046: end_line();
! 1047: }
! 1048:
! 1049:
! 1050: /*
! 1051: check_residue()
! 1052: takes care of any effect of the monster
! 1053: */
! 1054:
! 1055: void
! 1056: check_residue(struct thing *tp)
! 1057: {
! 1058: /* Take care of special abilities */
! 1059:
! 1060: if (on(*tp, DIDHOLD) && (--hold_count == 0))
! 1061: turn_off(player, ISHELD);
! 1062:
! 1063: /* If it has lowered player, give him back a level, maybe */
! 1064:
! 1065: if (on(*tp, DIDDRAIN) && rnd(3) == 0)
! 1066: raise_level();
! 1067:
! 1068: /* If frightened of this monster, stop */
! 1069:
! 1070: if (on(player, ISFLEE) && (player.t_chasee==tp))
! 1071: turn_off(player, ISFLEE);
! 1072:
! 1073: /* If monster was suffocating player, stop it */
! 1074: if (on(*tp, DIDSUFFOCATE))
! 1075: extinguish_fuse(FUSE_SUFFOCATE);
! 1076:
! 1077: /* If something with fire, may darken */
! 1078: if (on(*tp, HASFIRE))
! 1079: {
! 1080: struct room *rp = roomin(tp->t_pos);
! 1081:
! 1082: if (rp && (--(rp->r_fires) <= 0))
! 1083: {
! 1084: rp->r_flags &= ~HASFIRE;
! 1085: light(&tp->t_pos);
! 1086: }
! 1087: }
! 1088: }
! 1089:
! 1090: /*
! 1091: sell()
! 1092: displays a menu of goods from which the player may choose to
! 1093: purchase something.
! 1094: */
! 1095:
! 1096: #define SELL_ITEMS 10 /* How many things 'q' might carry */
! 1097:
! 1098: void
! 1099: sell(struct thing *tp)
! 1100: {
! 1101: struct linked_list *item;
! 1102: int i, j, min_worth, nitems, chance, which_item, w;
! 1103: char goods;
! 1104: struct object *obj;
! 1105: char buffer[2 * LINELEN];
! 1106: char dbuf[2 * LINELEN];
! 1107:
! 1108: struct
! 1109: {
! 1110: int which;
! 1111: int plus1, plus2;
! 1112: int count;
! 1113: int worth;
! 1114: int flags;
! 1115: char *name;
! 1116: }
! 1117: selection[SELL_ITEMS];
! 1118:
! 1119: int effective_purse = ((player.t_ctype == C_PALADIN) ?
! 1120: (9 * purse / 10) : purse);
! 1121:
! 1122: min_worth = -1; /* hope item is never worth less than this */
! 1123: item = find_mons(tp->t_pos.y, tp->t_pos.x); /* Get pointer to monster */
! 1124:
! 1125: /* Select the items */
! 1126:
! 1127: nitems = rnd(6) + 5;
! 1128:
! 1129: switch (rnd(6))
! 1130: {
! 1131: /* Armor */
! 1132: case 0:
! 1133: case 1:
! 1134: goods = ARMOR;
! 1135: for (i = 0; i < nitems; i++)
! 1136: {
! 1137: chance = rnd(100);
! 1138:
! 1139: for (j = 0; j < maxarmors; j++)
! 1140: if (chance < armors[j].a_prob)
! 1141: break;
! 1142:
! 1143: if (j == maxarmors)
! 1144: {
! 1145: debug("Picked a bad armor %d", chance);
! 1146: j = 0;
! 1147: }
! 1148:
! 1149: selection[i].which = j;
! 1150: selection[i].count = 1;
! 1151:
! 1152: if (rnd(100) < 40)
! 1153: selection[i].plus1 = rnd(5) + 1;
! 1154: else
! 1155: selection[i].plus1 = 0;
! 1156:
! 1157: selection[i].name = armors[j].a_name;
! 1158:
! 1159: switch (luck)
! 1160: {
! 1161: case 0: break;
! 1162: case 1:
! 1163: if (rnd(3) == 0)
! 1164: {
! 1165: selection[i].flags |= ISCURSED;
! 1166: selection[i].plus1 = -1 - rnd(5);
! 1167: }
! 1168: break;
! 1169:
! 1170: default:
! 1171: if (rnd(luck))
! 1172: {
! 1173: selection[i].flags |= ISCURSED;
! 1174: selection[i].plus1 = -1 - rnd(5);
! 1175: }
! 1176: break;
! 1177: }
! 1178:
! 1179: /* Calculate price */
! 1180:
! 1181: w = armors[j].a_worth;
! 1182: w *= (1 + luck + (10 * selection[i].plus1));
! 1183: w = (w / 2) + (roll(6, w) / 6);
! 1184: selection[i].worth = max(w, 25);
! 1185:
! 1186: if (min_worth > selection[i].worth || i == 1)
! 1187: min_worth = selection[i].worth;
! 1188: }
! 1189: break;
! 1190:
! 1191: /* Weapon */
! 1192: case 2:
! 1193: case 3:
! 1194: goods = WEAPON;
! 1195: for (i = 0; i < nitems; i++)
! 1196: {
! 1197: selection[i].which = rnd(maxweapons);
! 1198: selection[i].count = 1;
! 1199:
! 1200: if (rnd(100) < 35)
! 1201: {
! 1202: selection[i].plus1 = rnd(3);
! 1203: selection[i].plus2 = rnd(3);
! 1204: }
! 1205: else
! 1206: {
! 1207: selection[i].plus1 = 0;
! 1208: selection[i].plus2 = 0;
! 1209: }
! 1210:
! 1211: if (weaps[selection[i].which].w_flags & ISMANY)
! 1212: selection[i].count = rnd(15) + 8;
! 1213:
! 1214: selection[i].name = weaps[selection[i].which].w_name;
! 1215:
! 1216: switch (luck)
! 1217: {
! 1218: case 0: break;
! 1219: case 1:
! 1220: if (rnd(3) == 0)
! 1221: {
! 1222: selection[i].flags |= ISCURSED;
! 1223: selection[i].plus1 = -rnd(3);
! 1224: selection[i].plus2 = -rnd(3);
! 1225: }
! 1226: break;
! 1227:
! 1228: default:
! 1229: if (rnd(luck))
! 1230: {
! 1231: selection[i].flags |= ISCURSED;
! 1232: selection[i].plus1 = -rnd(3);
! 1233: selection[i].plus2 = -rnd(3);
! 1234: }
! 1235: break;
! 1236: }
! 1237:
! 1238: w = weaps[selection[i].which].w_worth * selection[i].count;
! 1239: w *= (1 + luck + (10 * selection[i].plus1 +
! 1240: 10 * selection[i].plus2));
! 1241: w = (w / 2) + (roll(6, w) / 6);
! 1242: selection[i].worth = max(w, 25);
! 1243:
! 1244: if (min_worth > selection[i].worth || i == 1)
! 1245: min_worth = selection[i].worth;
! 1246: }
! 1247: break;
! 1248:
! 1249: /* Staff or wand */
! 1250: case 4:
! 1251: goods = STICK;
! 1252:
! 1253: for (i = 0; i < nitems; i++)
! 1254: {
! 1255: selection[i].which = pick_one(ws_magic, maxsticks);
! 1256: selection[i].plus1 = rnd(11) + 5;
! 1257: selection[i].count = 1;
! 1258: selection[i].name = ws_magic[selection[i].which].mi_name;
! 1259:
! 1260: switch (luck)
! 1261: {
! 1262: case 0: break;
! 1263: case 1:
! 1264: if (rnd(3) == 0)
! 1265: {
! 1266: selection[i].flags |= ISCURSED;
! 1267: selection[i].plus1 = 1;
! 1268: }
! 1269: break;
! 1270:
! 1271: default:
! 1272: if (rnd(luck))
! 1273: {
! 1274: selection[i].flags |= ISCURSED;
! 1275: selection[i].plus1 = 1;
! 1276: }
! 1277: }
! 1278:
! 1279: w = ws_magic[selection[i].which].mi_worth;
! 1280: w += (luck + 1) * 20 * selection[i].plus1;
! 1281: w = (w / 2) + (roll(6, w) / 6);
! 1282: selection[i].worth = max(w, 25);
! 1283:
! 1284: if (min_worth > selection[i].worth || i == 1)
! 1285: min_worth = selection[i].worth;
! 1286: }
! 1287: break;
! 1288:
! 1289: /* Ring */
! 1290:
! 1291: case 5:
! 1292: goods = RING;
! 1293: for (i = 0; i < nitems; i++)
! 1294: {
! 1295: selection[i].which = pick_one(r_magic, maxrings);
! 1296: selection[i].plus1 = rnd(2) + 1;
! 1297: selection[i].count = 1;
! 1298:
! 1299: if (rnd(100) < r_magic[selection[i].which].mi_bless + 10)
! 1300: selection[i].plus1 += rnd(2) + 1;
! 1301:
! 1302: selection[i].name = r_magic[selection[i].which].mi_name;
! 1303:
! 1304: switch (luck)
! 1305: {
! 1306: case 0: break;
! 1307: case 1:
! 1308: if (rnd(3) == 0)
! 1309: {
! 1310: selection[i].flags |= ISCURSED;
! 1311: selection[i].plus1 = -1 - rnd(2);
! 1312: }
! 1313: break;
! 1314:
! 1315: default:
! 1316: if (rnd(luck))
! 1317: {
! 1318: selection[i].flags |= ISCURSED;
! 1319: selection[i].plus1 = -1 - rnd(2);
! 1320: }
! 1321: }
! 1322:
! 1323: w = r_magic[selection[i].which].mi_worth;
! 1324:
! 1325: switch(selection[i].which)
! 1326: {
! 1327: case R_DIGEST:
! 1328: if (selection[i].plus1 > 2)
! 1329: selection[i].plus1 = 2;
! 1330: else if (selection[i].plus1 < 1)
! 1331: selection[i].plus1 = 1;
! 1332: /* fall thru here to other cases */
! 1333: case R_ADDSTR:
! 1334: case R_ADDDAM:
! 1335: case R_PROTECT:
! 1336: case R_ADDHIT:
! 1337: case R_ADDINTEL:
! 1338: case R_ADDWISDOM:
! 1339: if (selection[i].plus1 > 0)
! 1340: w += selection[i].plus1 * 50;
! 1341: }
! 1342:
! 1343: w *= (1 + luck);
! 1344: w = (w / 2) + (roll(6, w) / 6);
! 1345: selection[i].worth = max(w, 25);
! 1346:
! 1347: if (min_worth > selection[i].worth * selection[i].count)
! 1348: min_worth = selection[i].worth;
! 1349: }
! 1350: }
! 1351:
! 1352: /* See if player can afford an item */
! 1353:
! 1354: if (min_worth > effective_purse)
! 1355: {
! 1356: msg("The %s eyes your small purse and departs.",
! 1357: monsters[nummonst].m_name);
! 1358:
! 1359: /* Get rid of the monster */
! 1360:
! 1361: killed(NULL, item, NOMESSAGE, NOPOINTS);
! 1362:
! 1363: return;
! 1364: }
! 1365:
! 1366: /* Display the goods */
! 1367:
! 1368: msg("The %s shows you his wares.", monsters[nummonst].m_name);
! 1369: wstandout(cw);
! 1370: mvwaddstr(cw, 0, mpos, morestr);
! 1371: wstandend(cw);
! 1372: wrefresh(cw);
! 1373: wait_for(' ');
! 1374: msg("");
! 1375: clearok(cw, TRUE);
! 1376: touchwin(cw);
! 1377:
! 1378: wclear(hw);
! 1379: touchwin(hw);
! 1380:
! 1381: for (i = 0; i < nitems; i++)
! 1382: {
! 1383: if (selection[i].worth > effective_purse)
! 1384: continue;
! 1385:
! 1386: wmove(hw, i + 2, 0);
! 1387: sprintf(dbuf, "[%c] ", ('a' + i));
! 1388:
! 1389: switch(goods)
! 1390: {
! 1391: case ARMOR:
! 1392: strcat(dbuf, "Some ");
! 1393: break;
! 1394: case WEAPON:
! 1395: if (selection[i].count == 1)
! 1396: strcat(dbuf, "A ");
! 1397: else
! 1398: {
! 1399: sprintf(buffer, "%2d ", selection[i].count);
! 1400: strcat(dbuf, buffer);
! 1401: }
! 1402: break;
! 1403:
! 1404: case STICK:
! 1405: strcat(dbuf, "A ");
! 1406: strcat(dbuf, ws_type[selection[i].which]);
! 1407: strcat(dbuf, " of ");
! 1408: break;
! 1409:
! 1410: case RING:
! 1411: strcat(dbuf, "A ring of ");
! 1412: break;
! 1413: }
! 1414:
! 1415: strcat(dbuf, selection[i].name);
! 1416:
! 1417: if (selection[i].count > 1)
! 1418: strcat(dbuf, "s");
! 1419:
! 1420: sprintf(buffer, "%-50.80s Price: %d", dbuf, selection[i].worth);
! 1421: waddstr(hw, buffer);
! 1422: }
! 1423:
! 1424: sprintf(buffer, "Purse: %ld", purse);
! 1425: mvwaddstr(hw, nitems + 3, 0, buffer);
! 1426: mvwaddstr(hw, 0, 0, "How about one of the following goods? ");
! 1427: wrefresh(hw);
! 1428:
! 1429: /* Get rid of the monster */
! 1430:
! 1431: killed(NULL, item, NOMESSAGE, NOPOINTS);
! 1432:
! 1433: which_item = (short) ((readchar() & 0177) - 'a');
! 1434:
! 1435: while (which_item < 0 || which_item >= nitems ||
! 1436: selection[which_item].worth > effective_purse)
! 1437: {
! 1438: if (which_item == (short) ESCAPE - (short) 'a')
! 1439: return;
! 1440:
! 1441: mvwaddstr(hw, 0, 0, "Please enter one of the listed items: ");
! 1442: wrefresh(hw);
! 1443: which_item = (short) ((readchar() & 0177) - 'a');
! 1444: }
! 1445:
! 1446: if (purse > selection[which_item].worth)
! 1447: purse -= selection[which_item].worth;
! 1448: else
! 1449: purse = 0L;
! 1450:
! 1451: item = spec_item(goods, selection[which_item].which,
! 1452: selection[which_item].plus1, selection[which_item].plus2);
! 1453:
! 1454: obj = OBJPTR(item);
! 1455:
! 1456: if (selection[which_item].count > 1)
! 1457: {
! 1458: obj->o_count = selection[which_item].count;
! 1459: obj->o_group = ++group;
! 1460: }
! 1461:
! 1462: /* If a stick or ring, let player know the type */
! 1463:
! 1464: switch (goods)
! 1465: {
! 1466: case STICK: know_items[TYP_STICK][selection[which_item].which] = TRUE;
! 1467: break;
! 1468: case RING: know_items[TYP_RING][selection[which_item].which] = TRUE;
! 1469: break;
! 1470: }
! 1471:
! 1472: if (add_pack(item, MESSAGE) == FALSE)
! 1473: {
! 1474: obj->o_pos = hero;
! 1475: fall(&player, item, TRUE, FALSE);
! 1476: }
! 1477: }
! 1478:
! 1479: void
! 1480: carried_weapon(struct thing *owner, struct object *weapon)
! 1481: {
! 1482: weapon->o_hplus = (rnd(4) < 3) ? 0 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
! 1483: weapon->o_dplus = (rnd(4) < 3) ? 0 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
! 1484: weapon->o_hplus += rnd(owner->t_stats.s_lvl / 3 + 1);
! 1485: weapon->o_hplus += rnd(owner->t_stats.s_lvl / 3 + 1);
! 1486: weapon->o_damage = weapon->o_hurldmg = "0d0";
! 1487: weapon->o_ac = 11;
! 1488: weapon->o_count = 1;
! 1489: weapon->o_group = 0;
! 1490:
! 1491: if ((weapon->o_hplus <= 0) && (weapon->o_dplus <= 0))
! 1492: weapon->o_flags = ISCURSED;
! 1493:
! 1494: weapon->o_flags = 0;
! 1495: weapon->o_type = WEAPON;
! 1496: weapon->o_mark[0] = '\0';
! 1497: }
CVSweb