Annotation of early-roguelike/urogue/fight.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: fight.c - All the fighting gets done here
! 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: * This are the beginning experience levels for all players all further
! 26: * experience levels are computed by multiplying by 2
! 27: */
! 28:
! 29: static long e_levels[10] =
! 30: {
! 31: 143L, /* Fighter */
! 32: 182L, /* Paladin */
! 33: 169L, /* Ranger */
! 34: 127L, /* Cleric */
! 35: 154L, /* Druid */
! 36: 185L, /* Magician */
! 37: 169L, /* Illusionist */
! 38: 112L, /* Thief */
! 39: 126L, /* Assasin */
! 40: 319L /* Ninja */
! 41: };
! 42:
! 43: static struct matrix att_mat[11] =
! 44: {
! 45: /* Base, Max_lvl, Factor, Offset, Range */
! 46:
! 47: { 10, 17, 2, 1, 2 }, /* fi */
! 48: { 10, 17, 2, 1, 2 }, /* pa */
! 49: { 10, 17, 2, 1, 2 }, /* ra */
! 50: { 10, 19, 2, 1, 3 }, /* cl */
! 51: { 10, 19, 2, 1, 3 }, /* dr */
! 52: { 9, 21, 2, 1, 5 }, /* mu */
! 53: { 9, 21, 2, 1, 5 }, /* il */
! 54: { 10, 21, 2, 1, 4 }, /* th */
! 55: { 10, 21, 2, 1, 4 }, /* as */
! 56: { 10, 21, 2, 1, 4 }, /* nj */
! 57: { 7, 25, 1, 0, 2 } /* mn */
! 58: };
! 59:
! 60: void
! 61: do_fight(coord dir, int tothedeath)
! 62: {
! 63: int x,y;
! 64:
! 65: x = dir.x;
! 66: y = dir.y;
! 67:
! 68: if (!tothedeath && pstats.s_hpt < max_stats.s_hpt / 3)
! 69: {
! 70: msg("That's not wise.");
! 71:
! 72: after = fighting = FALSE;
! 73: return;
! 74: }
! 75:
! 76: if (isalpha(CCHAR(winat(hero.y + y, hero.x + x))))
! 77: {
! 78: after = fighting = TRUE;
! 79: do_move(y, x);
! 80: }
! 81: else
! 82: {
! 83: if (fighting == FALSE)
! 84: msg("Nothing there.");
! 85:
! 86: after = fighting = FALSE;
! 87: }
! 88:
! 89: return;
! 90: }
! 91:
! 92: /*
! 93: fight()
! 94: The player attacks the monster.
! 95: */
! 96:
! 97: int
! 98: fight(coord *mp, struct object *weap, int thrown)
! 99: {
! 100: struct thing *tp;
! 101: struct linked_list *item;
! 102: int did_hit = TRUE;
! 103: char *mname;
! 104:
! 105: /* Find the monster we want to fight */
! 106:
! 107: if ((item = find_mons(mp->y, mp->x)) == NULL)
! 108: {
! 109: debug("Fight what @ %d,%d", mp->y, mp->x);
! 110: return 0;
! 111: }
! 112:
! 113: tp = THINGPTR(item);
! 114:
! 115: mname = (on(player, ISBLIND)) ? "it" : monsters[tp->t_index].m_name;
! 116:
! 117: /* Since we are fighting, things are not quiet so no healing takes place */
! 118:
! 119: player.t_rest_hpt = player.t_rest_pow = 0;
! 120: tp->t_rest_hpt = tp->t_rest_pow = 0;
! 121:
! 122: /* Let him know it was really a mimic (if it was one). */
! 123:
! 124: if (off(player, ISBLIND))
! 125: {
! 126: if (on(*tp, ISDISGUISE) && (tp->t_type != tp->t_disguise))
! 127: {
! 128: msg("Wait! That's a %s!", mname);
! 129: turn_off(*tp, ISDISGUISE);
! 130: did_hit = thrown;
! 131: }
! 132:
! 133: if (on(*tp, CANSURPRISE))
! 134: {
! 135: turn_off(*tp, CANSURPRISE);
! 136: if ((player.t_ctype == C_RANGER && rnd(6) != 0) ||
! 137: (player.t_ctype == C_NINJA && rnd(pstats.s_lvl / 2)
! 138: != 0))
! 139: msg("You notice a %s trying to hide!", mname);
! 140: else
! 141: {
! 142: msg("Wait! There's a %s!", mname);
! 143: did_hit = thrown;
! 144: }
! 145: }
! 146: }
! 147:
! 148: /* Protection from Normal Missiles */
! 149:
! 150: if (thrown && on(*tp, HASMSHIELD))
! 151: {
! 152: msg("The %s slows as it approaches %s.",
! 153: weaps[weap->o_which].w_name, mname);
! 154:
! 155: did_hit = FALSE;
! 156: }
! 157:
! 158: if (did_hit)
! 159: {
! 160: did_hit = FALSE;
! 161:
! 162: if (!can_blink(tp) &&
! 163: (off(*tp, MAGICHIT) || (weap != NULL &&
! 164: (weap->o_hplus > 0 || weap->o_dplus > 0))) &&
! 165: (off(*tp, BMAGICHIT) || (weap != NULL &&
! 166: (weap->o_hplus > 2 || weap->o_dplus > 2))) &&
! 167: roll_em(&player, tp, weap, thrown, cur_weapon))
! 168: {
! 169: did_hit = TRUE;
! 170: tp->t_wasshot = TRUE;
! 171:
! 172: if (thrown)
! 173: {
! 174: if (weap != NULL && weap->o_type == WEAPON
! 175: && weap->o_which == GRENADE)
! 176: {
! 177: hearmsg("BOOOM!");
! 178: aggravate();
! 179: }
! 180:
! 181: thunk(weap, mname);
! 182: }
! 183: else
! 184: hit(mname);
! 185:
! 186: /* hitting a friendly monster is curtains */
! 187:
! 188: if (on(*tp, ISFRIENDLY))
! 189: {
! 190: turn_off(*tp, ISFRIENDLY);
! 191: turn_on(*tp, ISMEAN);
! 192: }
! 193:
! 194: /* Charmed monsters become uncharmed */
! 195:
! 196: if (on(*tp, ISCHARMED))
! 197: {
! 198: turn_off(*tp, ISCHARMED);
! 199: turn_on(*tp, ISMEAN);
! 200: }
! 201:
! 202: /*
! 203: * If the player hit a rust monster, he better have a
! 204: * + weapon
! 205: */
! 206:
! 207: if (on(*tp, CANRUST))
! 208: {
! 209: if (!thrown && (weap != NULL) &&
! 210: (weap->o_flags & ISMETAL) &&
! 211: !(weap->o_flags & ISPROT) &&
! 212: !(weap->o_flags & ISSILVER) &&
! 213: (weap->o_hplus < 1) && (weap->o_dplus < 1))
! 214: {
! 215: if (rnd(100) < 50)
! 216: weap->o_hplus--;
! 217: else
! 218: weap->o_dplus--;
! 219:
! 220: msg("Your %s weakens!", weaps[weap->o_which].w_name);
! 221: }
! 222: else if (!thrown && weap != NULL && (weap->o_flags & ISMETAL))
! 223: msg("The rust vanishes from your %s!",
! 224: weaps[weap->o_which].w_name);
! 225: }
! 226:
! 227: /* flammable monsters die from burning weapons */
! 228:
! 229: if (thrown && on(*tp, CANBBURN) &&
! 230: (weap->o_flags & CANBURN) &&
! 231: !save_throw(VS_WAND, tp))
! 232: {
! 233: msg("The %s vanishes in a ball of flame.",
! 234: monsters[tp->t_index].m_name);
! 235:
! 236: tp->t_stats.s_hpt = 0;
! 237: }
! 238:
! 239: /* spores explode and infest hero */
! 240:
! 241: if (on(*tp, CANSPORE))
! 242: {
! 243: msg("The %s explodes in a cloud of dust.",
! 244: monsters[tp->t_index].m_name);
! 245:
! 246: if (is_wearing(R_HEALTH) ||
! 247: player.t_ctype == C_PALADIN ||
! 248: (player.t_ctype == C_NINJA && pstats.s_lvl
! 249: > 6) ||
! 250: thrown && rnd(50) > 0 ||
! 251: rnd(20) > 0)
! 252: {
! 253: msg("The dust makes it hard to breath.");
! 254: }
! 255: else
! 256: {
! 257: msg("You have contracted a parasitic infestation!");
! 258:
! 259: infest_dam++;
! 260: turn_on(player, HASINFEST);
! 261: }
! 262:
! 263: tp->t_stats.s_hpt = 0;
! 264: }
! 265:
! 266: /* fireproof monsters laugh at you when burning weapon hits */
! 267:
! 268: if (thrown && on(*tp, NOFIRE) && (weap->o_flags & CANBURN))
! 269: msg("The %s laughs as the %s bounces.",
! 270: monsters[tp->t_index].m_name,
! 271: weaps[weap->o_which].w_name);
! 272:
! 273: /* sharp weapons have no effect on NOSHARP monsters */
! 274:
! 275: if (on(*tp, NOSHARP) && (weap != NULL) &&
! 276: (weap->o_flags & ISSHARP))
! 277: {
! 278: msg("The %s has no effect on the %s!",
! 279: weaps[weap->o_which].w_name,
! 280: monsters[tp->t_index].m_name);
! 281:
! 282: fighting = FALSE;
! 283: }
! 284:
! 285: /* metal weapons pass through NOMETAL monsters */
! 286:
! 287: if (on(*tp, NOMETAL) && (weap != NULL) &&
! 288: (weap->o_flags & ISMETAL))
! 289: {
! 290: msg("The %s passes through the %s!",
! 291: weaps[weap->o_which].w_name,
! 292: monsters[tp->t_index].m_name);
! 293:
! 294: fighting = FALSE;
! 295: }
! 296:
! 297: /*
! 298: * If the player hit something that shrieks, wake the
! 299: * dungeon
! 300: */
! 301:
! 302: if (on(*tp, CANSHRIEK))
! 303: {
! 304: turn_off(*tp, CANSHRIEK);
! 305:
! 306: if (on(player, CANHEAR))
! 307: {
! 308: msg("You are stunned by the %s's shriek.", mname);
! 309: no_command += 4 + rnd(8);
! 310: }
! 311: else if (off(player, ISDEAF))
! 312: msg("The %s emits a piercing shriek.", mname);
! 313: else
! 314: msg("The %s seems to be trying to make some noise.", mname);
! 315:
! 316: aggravate();
! 317:
! 318: if (rnd(wizard ? 3 : 39) == 0 && cur_armor
! 319: != NULL
! 320: && cur_armor->o_which == CRYSTAL_ARMOR)
! 321: {
! 322: struct linked_list *itm;
! 323: struct object *obj;
! 324:
! 325: for (itm = pack; itm != NULL; itm = next(itm))
! 326: {
! 327: obj = OBJPTR(itm);
! 328:
! 329: if (obj == cur_armor)
! 330: break;
! 331: }
! 332:
! 333: if (itm == NULL)
! 334: debug("Can't find crystalline armor being worn.");
! 335: else
! 336: {
! 337: msg("Your armor shatters from the shriek.");
! 338: cur_armor = NULL;
! 339: del_pack(itm);
! 340: }
! 341: }
! 342: }
! 343:
! 344: /*
! 345: * If the player hit something that can surprise, it
! 346: * can't now
! 347: */
! 348:
! 349: if (on(*tp, CANSURPRISE))
! 350: turn_off(*tp, CANSURPRISE);
! 351:
! 352: /*
! 353: * If the player hit something that can summon, it
! 354: * will try to
! 355: */
! 356:
! 357: summon_help(tp, NOFORCE);
! 358:
! 359: /* Can the player confuse? */
! 360:
! 361: if (on(player, CANHUH) && !thrown)
! 362: {
! 363: seemsg("Your hands stop glowing red!");
! 364: seemsg("The %s appears confused.", mname);
! 365: turn_on(*tp, ISHUH);
! 366: turn_off(player, CANHUH);
! 367: }
! 368:
! 369: /* Merchants just disappear if hit */
! 370:
! 371: /*
! 372: * increases prices and curses objects from now on
! 373: * though
! 374: */
! 375:
! 376: if (on(*tp, CANSELL))
! 377: {
! 378: msg("The %s disappears with his wares with a BOOM and a flash.",
! 379: mname);
! 380: killed(NULL, item, NOMESSAGE, NOPOINTS);
! 381: aggravate();
! 382: luck++;
! 383: }
! 384: else if (tp->t_stats.s_hpt <= 0)
! 385: killed(&player, item, MESSAGE, POINTS);
! 386:
! 387: /*
! 388: * If the monster is fairly intelligent and about to
! 389: * die, it may turn tail and run.
! 390: */
! 391:
! 392: else if ((tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt / 10)) &&
! 393: (rnd(25) < tp->t_stats.s_intel))
! 394: {
! 395: turn_on(*tp, ISFLEE);
! 396:
! 397: /* If monster was suffocating, stop it */
! 398:
! 399: if (on(*tp, DIDSUFFOCATE))
! 400: {
! 401: turn_off(*tp, DIDSUFFOCATE);
! 402: extinguish_fuse(FUSE_SUFFOCATE);
! 403: }
! 404:
! 405: /* If monster held us, stop it */
! 406:
! 407: if (on(*tp, DIDHOLD) && (--hold_count == 0))
! 408: turn_off(player, ISHELD);
! 409:
! 410: turn_off(*tp, DIDHOLD);
! 411:
! 412: if (on(*tp, CANTELEPORT))
! 413: {
! 414: int rm;
! 415:
! 416: /*
! 417: * Erase the monster from the old
! 418: * position
! 419: */
! 420:
! 421: if (isalpha(mvwinch(cw, tp->t_pos.y, tp->t_pos.x)))
! 422: mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
! 423:
! 424: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' ');
! 425:
! 426: /* Get a new position */
! 427:
! 428: do
! 429: {
! 430: rm = rnd_room();
! 431: rnd_pos(&rooms[rm], &tp->t_pos);
! 432: }
! 433: while (winat(tp->t_pos.y, tp->t_pos.x) != FLOOR);
! 434:
! 435: /* Put it there */
! 436:
! 437: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
! 438: tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
! 439: seemsg("The %s seems to have disappeared!", mname);
! 440: }
! 441: }
! 442: }
! 443: else if (thrown)
! 444: bounce(weap, mname);
! 445: else
! 446: miss(mname);
! 447: }
! 448:
! 449: if (curr_mons)
! 450: chase_it(mp,&player); /* after so that backstabbing can happen */
! 451:
! 452: count = 0;
! 453:
! 454: return(did_hit);
! 455: }
! 456:
! 457: /*
! 458: attack()
! 459: The monster attacks the player
! 460: */
! 461:
! 462: int
! 463: attack(struct thing *mp, struct object *weapon, int thrown)
! 464: {
! 465: char *mname;
! 466: int did_hit = FALSE;
! 467:
! 468: /* If the monster is in a wall, it cannot attack */
! 469:
! 470: if (on(*mp, ISINWALL))
! 471: return (FALSE);
! 472:
! 473: /* If two monsters start to gang up on our hero, stop fight mode */
! 474:
! 475: if (fighting)
! 476: {
! 477: if (beast == NULL)
! 478: beast = mp;
! 479: else if (beast != mp)
! 480: fighting = FALSE;
! 481: }
! 482:
! 483: /*
! 484: Since this is an attack, stop running and any healing that was
! 485: going on at the time.
! 486: */
! 487:
! 488: running = FALSE;
! 489: player.t_rest_hpt = player.t_rest_pow = 0;
! 490: mp->t_rest_hpt = mp->t_rest_pow = 0;
! 491:
! 492: if (on(*mp, ISDISGUISE) && off(player, ISBLIND))
! 493: turn_off(*mp, ISDISGUISE);
! 494: mname = on(player, ISBLIND) ? "the monster" :
! 495: monsters[mp->t_index].m_name;
! 496:
! 497: if (roll_em(mp, &player, weapon, thrown, wield_weap(weapon, mp)) &&
! 498: (!thrown || off(player, HASMSHIELD)))
! 499: {
! 500: did_hit = TRUE;
! 501:
! 502: m_thunk(weapon, mname);
! 503:
! 504: if (pstats.s_hpt <= 0)
! 505: {
! 506: death(mp->t_index); /* Bye bye life ... */
! 507: return TRUE;
! 508: }
! 509:
! 510: /* surprising monsters appear after they shoot at you */
! 511:
! 512: if (thrown && on(*mp, CANSURPRISE))
! 513: turn_off(*mp, CANSURPRISE);
! 514: else if (!thrown)
! 515: {
! 516:
! 517: /*
! 518: If a vampire hits, it may take half your hit
! 519: points
! 520: */
! 521:
! 522: if ( on(*mp, CANSUCK) && !save(VS_MAGIC) )
! 523: {
! 524: if (pstats.s_hpt == 1)
! 525: {
! 526: death(mp->t_index);
! 527: return TRUE;
! 528: }
! 529: else
! 530: {
! 531: pstats.s_hpt /= 2;
! 532: msg("You feel your life force being drawn from you.");
! 533: }
! 534: }
! 535:
! 536: /*
! 537: strong monsters can shatter or gong crystalline
! 538: armor
! 539: */
! 540:
! 541: if (cur_armor != NULL && cur_armor->o_which == CRYSTAL_ARMOR)
! 542: {
! 543: if (rnd(mp->t_stats.s_str + (cur_armor->o_ac / 2)) > 20)
! 544: {
! 545: struct linked_list *item;
! 546: struct object *obj;
! 547:
! 548: for (item = pack; item != NULL; item = next(item))
! 549: {
! 550: obj = OBJPTR(item);
! 551:
! 552: if (obj == cur_armor)
! 553: break;
! 554: }
! 555:
! 556: if (item == NULL)
! 557: debug("Can't find crystalline armor being worn.");
! 558: else
! 559: {
! 560: msg("Your armor is shattered by the blow.");
! 561: cur_armor = NULL;
! 562: del_pack(item);
! 563: }
! 564: }
! 565: else if (rnd(mp->t_stats.s_str) > 15)
! 566: {
! 567: msg("Your armor rings from the blow.");
! 568: aggravate();
! 569: }
! 570: }
! 571:
! 572: /* Stinking monsters reduce the player's strength */
! 573:
! 574: if (on(*mp, CANSTINK))
! 575: {
! 576: turn_off(*mp, CANSTINK);
! 577:
! 578: if (player.t_ctype != C_PALADIN
! 579: && !(player.t_ctype == C_NINJA && pstats.s_lvl > 12)
! 580: && !save(VS_POISON))
! 581: {
! 582: if (on(player, CANSCENT))
! 583: {
! 584: msg("You pass out from the stench of the %s.", mname);
! 585: no_command += 4 + rnd(8);
! 586: }
! 587: else if (off(player, ISUNSMELL))
! 588: msg("The stench of the %s sickens you.", mname);
! 589:
! 590: if (on(player, HASSTINK))
! 591: lengthen_fuse(FUSE_UNSTINK, STINKTIME);
! 592: else
! 593: {
! 594: turn_on(player, HASSTINK);
! 595: light_fuse(FUSE_UNSTINK, 0, STINKTIME, AFTER);
! 596: }
! 597: }
! 598: }
! 599:
! 600: /* chilling monster reduces strength permanently */
! 601:
! 602: if (on(*mp, CANCHILL) &&
! 603: (cur_armor == NULL || cur_armor->o_which != CRYSTAL_ARMOR))
! 604: {
! 605: msg("You cringe at the %s's chilling touch.", mname);
! 606:
! 607: if (!is_wearing(R_SUSABILITY))
! 608: {
! 609: chg_str(-1, FALSE, TRUE);
! 610:
! 611: if (lost_str == 0)
! 612: light_fuse(FUSE_RES_STRENGTH, 0, CHILLTIME, AFTER);
! 613: else
! 614: lengthen_fuse(FUSE_RES_STRENGTH, CHILLTIME);
! 615: }
! 616: }
! 617:
! 618: /* itching monsters reduce dexterity (temporarily) */
! 619:
! 620: if (on(*mp, CANITCH) && player.t_ctype != C_PALADIN
! 621: && !(player.t_ctype == C_NINJA && pstats.s_lvl > 12)
! 622: && !save(VS_POISON))
! 623: {
! 624: msg("The claws of the %s scratch you!", mname);
! 625:
! 626: if (is_wearing(R_SUSABILITY))
! 627: msg("The scratch has no effect.");
! 628: else
! 629: {
! 630: msg("You feel a burning itch.");
! 631: turn_on(player, HASITCH);
! 632: chg_dext(-1, FALSE, TRUE);
! 633: light_fuse(FUSE_UNITCH, 0, roll(4, 6), AFTER);
! 634: }
! 635: }
! 636:
! 637: /* a hugging monster may SQUEEEEEEEZE */
! 638:
! 639: if (on(*mp, CANHUG) &&
! 640: (cur_armor == NULL || cur_armor->o_which != CRYSTAL_ARMOR))
! 641: {
! 642: if (roll(1, 20) >= 18 || roll(1, 20) >= 18)
! 643: {
! 644: msg("The %s squeezes you against itself.", mname);
! 645:
! 646: if ((pstats.s_hpt -= roll(2, 8)) <= 0)
! 647: {
! 648: death(mp->t_index);
! 649: return TRUE;
! 650: }
! 651: }
! 652: }
! 653:
! 654: /* a trampling monster may step on the player */
! 655:
! 656: if (on(*mp, CANTRAMPLE))
! 657: {
! 658: if (roll(1, 20) >= 16 || roll(1, 20) >= 16)
! 659: {
! 660: msg("The %s steps on you.", mname);
! 661:
! 662: if ((pstats.s_hpt -= roll(3, mp->t_stats.s_lvl)) <= 0)
! 663: {
! 664: death(mp->t_index);
! 665: return TRUE;
! 666: }
! 667: }
! 668: }
! 669:
! 670: /* a disease-carrying monster may transmit the disease */
! 671:
! 672: if (on(*mp, CANDISEASE) &&
! 673: (rnd(pstats.s_const) < mp->t_stats.s_lvl) &&
! 674: off(player, HASDISEASE))
! 675: {
! 676:
! 677: if (is_wearing(R_HEALTH)
! 678: || (player.t_ctype == C_PALADIN)
! 679: || (player.t_ctype == C_NINJA &&
! 680: pstats.s_lvl > 6))
! 681: msg("The wound heals quickly.");
! 682: else
! 683: {
! 684: turn_on(player, HASDISEASE);
! 685: light_fuse(FUSE_CURE_DISEASE,0,roll(4,4) * SICKTIME, AFTER);
! 686: msg("You have contracted a disease!");
! 687: }
! 688: }
! 689:
! 690: /* a rust monster will weaken your armor */
! 691:
! 692: if (on(*mp, CANRUST))
! 693: {
! 694: if (cur_armor != NULL &&
! 695: cur_armor->o_which != SOFT_LEATHER &&
! 696: cur_armor->o_which != HEAVY_LEATHER &&
! 697: cur_armor->o_which != CUIRBOLILLI &&
! 698: cur_armor->o_which != PADDED_ARMOR &&
! 699: cur_armor->o_which != CRYSTAL_ARMOR &&
! 700: cur_armor->o_which != MITHRIL &&
! 701: !(cur_armor->o_flags & ISPROT) &&
! 702: cur_armor->o_ac < pstats.s_arm + 1)
! 703: {
! 704: msg("Your armor weakens!");
! 705: cur_armor->o_ac++;
! 706: }
! 707: else if (cur_armor != NULL &&
! 708: (cur_armor->o_flags & ISPROT) &&
! 709: cur_armor->o_which != SOFT_LEATHER &&
! 710: cur_armor->o_which != HEAVY_LEATHER &&
! 711: cur_armor->o_which != CUIRBOLILLI &&
! 712: cur_armor->o_which != PADDED_ARMOR &&
! 713: cur_armor->o_which != CRYSTAL_ARMOR &&
! 714: cur_armor->o_which != MITHRIL)
! 715: msg("The rust vanishes instantly!");
! 716: }
! 717:
! 718: /* If a surprising monster hit you, you can see it now */
! 719:
! 720: if (on(*mp, CANSURPRISE))
! 721: turn_off(*mp, CANSURPRISE);
! 722:
! 723: /* an infesting monster will give you a parasite or rot */
! 724:
! 725: if (on(*mp, CANINFEST) && rnd(pstats.s_const) < mp->t_stats.s_lvl)
! 726: {
! 727: if (is_wearing(R_HEALTH) || (player.t_ctype == C_PALADIN)
! 728: || (player.t_ctype == C_NINJA && pstats.s_lvl > 6))
! 729: msg("The wound quickly heals.");
! 730: else
! 731: {
! 732: turn_off(*mp, CANINFEST);
! 733: msg("You have contracted a parasitic infestation!");
! 734: infest_dam++;
! 735: turn_on(player, HASINFEST);
! 736: }
! 737: }
! 738:
! 739: /* Some monsters have poisonous bites */
! 740:
! 741: if (on(*mp, CANPOISON) && !save(VS_POISON))
! 742: {
! 743: if (is_wearing(R_SUSABILITY) || (player.t_ctype == C_PALADIN)
! 744: || (player.t_ctype == C_NINJA && pstats.s_lvl > 12))
! 745: msg("The sting has no effect on you!");
! 746: else
! 747: {
! 748: chg_str(-1, FALSE, FALSE);
! 749: msg("You feel a sting in your arm and now feel weaker.");
! 750: }
! 751: }
! 752:
! 753: /* a hideous monster may cause fear by touching */
! 754:
! 755: if (on(*mp, TOUCHFEAR))
! 756: {
! 757: turn_off(*mp, TOUCHFEAR);
! 758:
! 759: if (!save(VS_WAND)&&!(on(player,ISFLEE)&&(player.t_chasee==mp)))
! 760: {
! 761: if (off(player, SUPERHERO)
! 762: && (player.t_ctype != C_PALADIN))
! 763: {
! 764: turn_on(player, ISFLEE);
! 765: player.t_ischasing = FALSE;
! 766: player.t_chasee = mp;
! 767: msg("The %s's touch terrifies you.", mname);
! 768: }
! 769: else
! 770: msg("The %s's touch feels cold and clammy.", mname);
! 771: }
! 772: }
! 773:
! 774: /* some monsters will suffocate our hero */
! 775:
! 776: if (on(*mp, CANSUFFOCATE) && (rnd(100) < 15) &&
! 777: (find_slot(FUSE_SUFFOCATE, FUSE) == NULL))
! 778: {
! 779: turn_on(*mp, DIDSUFFOCATE);
! 780: msg("The %s is beginning to suffocate you.",
! 781: mname);
! 782: light_fuse(FUSE_SUFFOCATE, 0, roll(4, 2), AFTER);
! 783: }
! 784:
! 785: /* don't look now, you will get turned to stone */
! 786:
! 787: if (on(*mp, TOUCHSTONE))
! 788: {
! 789: turn_off(*mp, TOUCHSTONE);
! 790:
! 791: if (on(player, CANINWALL))
! 792: msg("The %s's touch has no effect.", mname);
! 793: else
! 794: {
! 795: if (!save(VS_PETRIFICATION) && rnd(100) < 3)
! 796: {
! 797: msg("Your body begins to solidify.");
! 798: msg("You are turned to stone !!! --More--");
! 799: wait_for(' ');
! 800: death(D_PETRIFY);
! 801: return TRUE;
! 802: }
! 803: else
! 804: {
! 805: msg("The %s's touch stiffens your limbs.", mname);
! 806: no_command = rnd(STONETIME) + 2;
! 807: }
! 808: }
! 809: }
! 810:
! 811: /* Undead might drain energy levels */
! 812:
! 813: if ((on(*mp, CANDRAIN) || on(*mp, DOUBLEDRAIN)) && rnd(100) < 15)
! 814: {
! 815: if (is_carrying(TR_AMULET))
! 816: msg("The Amulet protects you from the %s's negative energy!",
! 817: mname);
! 818: else
! 819: {
! 820: lower_level(mp->t_index);
! 821:
! 822: if (on(*mp, DOUBLEDRAIN))
! 823: lower_level(mp->t_index);
! 824: }
! 825:
! 826: turn_on(*mp, DIDDRAIN);
! 827: }
! 828:
! 829: /* permanently drain a wisdom point */
! 830:
! 831: if (on(*mp, DRAINWISDOM) && rnd(100) < 15)
! 832: {
! 833: int ring_str; /* Value of ring strengths */
! 834:
! 835: /* Undo any ring changes */
! 836:
! 837: ring_str = ring_value(R_ADDWISDOM) +
! 838: (on(player, POWERWISDOM) ? 10 : 0);
! 839:
! 840: pstats.s_wisdom -= ring_str;
! 841:
! 842: msg("You feel slightly less wise now.");
! 843:
! 844: pstats.s_wisdom = max(pstats.s_wisdom - 1, 3);
! 845: max_stats.s_wisdom = pstats.s_wisdom;
! 846:
! 847: /* Now put back the ring changes */
! 848:
! 849: pstats.s_wisdom += ring_str;
! 850:
! 851: }
! 852:
! 853: /* permanently drain a intelligence point */
! 854:
! 855: if (on(*mp, DRAINBRAIN) && rnd(100) < 15)
! 856: {
! 857: int ring_str; /* Value of ring strengths */
! 858:
! 859: /* Undo any ring changes */
! 860:
! 861: ring_str = ring_value(R_ADDINTEL) +
! 862: (on(player, POWERINTEL) ? 10 : 0);
! 863:
! 864: pstats.s_intel -= ring_str;
! 865:
! 866: msg("You feel slightly less intelligent now.");
! 867: pstats.s_intel = max(pstats.s_intel - 1, 3);
! 868: max_stats.s_intel = pstats.s_intel;
! 869:
! 870: /* Now put back the ring changes */
! 871:
! 872: pstats.s_intel += ring_str;
! 873: }
! 874:
! 875: /* Violet fungi and others hold the hero */
! 876:
! 877: if (on(*mp, CANHOLD) && off(*mp, DIDHOLD)
! 878: && !is_wearing(R_FREEDOM))
! 879: {
! 880: turn_on(player, ISHELD);
! 881: turn_on(*mp, DIDHOLD);
! 882: hold_count++;
! 883: }
! 884:
! 885: /* suckers will suck blood and run away */
! 886:
! 887: if (on(*mp, CANDRAW))
! 888: {
! 889: turn_off(*mp, CANDRAW);
! 890: turn_on(*mp, ISFLEE);
! 891: msg("The %s sates itself with your blood.", mname);
! 892:
! 893: if ((pstats.s_hpt -= 12) <= 0)
! 894: {
! 895: death(mp->t_index);
! 896: return TRUE;
! 897: }
! 898: }
! 899:
! 900: /* el stinkos will force a reduction in strength */
! 901:
! 902: if (on(*mp, CANSMELL))
! 903: {
! 904: turn_off(*mp, CANSMELL);
! 905:
! 906: if (save(VS_MAGIC) || is_wearing(R_SUSABILITY))
! 907: msg("You smell an unpleasant odor.");
! 908: else
! 909: {
! 910: int odor_str = -(rnd(6) + 1);
! 911:
! 912: if (on(player, CANSCENT))
! 913: {
! 914: msg("You pass out from a foul odor.");
! 915: no_command += 4 + rnd(8);
! 916: }
! 917: else if (off(player, ISUNSMELL))
! 918: msg("You are overcome by a foul odor.");
! 919:
! 920: if (lost_str == 0)
! 921: {
! 922: chg_str(odor_str, FALSE, TRUE);
! 923: light_fuse(FUSE_RES_STRENGTH, 0, SMELLTIME, AFTER);
! 924: }
! 925: else
! 926: lengthen_fuse(FUSE_RES_STRENGTH, SMELLTIME);
! 927: }
! 928: }
! 929:
! 930: /* Paralyzation */
! 931:
! 932: if (on(*mp, CANPARALYZE))
! 933: {
! 934: turn_off(*mp, CANPARALYZE);
! 935:
! 936: if (!save(VS_PARALYZATION) && no_command == 0)
! 937: {
! 938: if (on(player, CANINWALL))
! 939: msg("The %s's touch has no effect.", mname);
! 940: else
! 941: {
! 942: msg("The %s's touch paralyzes you.", mname);
! 943: no_command = FREEZETIME;
! 944: }
! 945: }
! 946: }
! 947:
! 948: /* Rotting */
! 949:
! 950: if (on(*mp, CANROT))
! 951: {
! 952: turn_off(*mp, CANROT);
! 953: turn_on(*mp, DOROT);
! 954: }
! 955:
! 956: /* some monsters steal gold */
! 957:
! 958: if (on(*mp, STEALGOLD))
! 959: {
! 960: long lastpurse;
! 961: struct linked_list *item;
! 962: struct object *obj;
! 963:
! 964: lastpurse = purse;
! 965: purse = (purse > GOLDCALC) ? purse - GOLDCALC : 0L;
! 966:
! 967: if (!save(VS_MAGIC))
! 968: purse = (purse > (4*GOLDCALC)) ? purse-(4*GOLDCALC) : 0L;
! 969:
! 970: if (purse != lastpurse)
! 971: {
! 972: msg("Your purse feels lighter.");
! 973:
! 974: /* Give the gold to the thief */
! 975:
! 976: for (item = mp->t_pack; item != NULL; item = next(item))
! 977: {
! 978: obj = OBJPTR(item);
! 979:
! 980: if (obj->o_type == GOLD)
! 981: {
! 982: obj->o_count += lastpurse - purse;
! 983: break;
! 984: }
! 985: }
! 986:
! 987: /* Did we do it? */
! 988:
! 989: if (item == NULL) /* Then make some */
! 990: {
! 991: item = new_item(sizeof *obj);
! 992: obj = OBJPTR(item);
! 993: obj->o_type = GOLD;
! 994: obj->o_count = lastpurse - purse;
! 995: obj->o_hplus = obj->o_dplus = 0;
! 996: obj->o_damage = obj->o_hurldmg = "0d0";
! 997: obj->o_ac = 11;
! 998: obj->o_group = 0;
! 999: obj->o_flags = 0;
! 1000: obj->o_mark[0] = '\0';
! 1001: obj->o_pos = mp->t_pos;
! 1002:
! 1003: attach(mp->t_pack, item);
! 1004: }
! 1005: }
! 1006:
! 1007: if (rnd(2))
! 1008: turn_on(*mp, ISFLEE);
! 1009:
! 1010: turn_on(*mp, ISINVIS);
! 1011: }
! 1012:
! 1013: /* other monsters steal magic */
! 1014:
! 1015: if (on(*mp, STEALMAGIC))
! 1016: {
! 1017: struct linked_list *list, *stealit;
! 1018: struct object *obj;
! 1019: int worth = 0;
! 1020:
! 1021: stealit = NULL;
! 1022:
! 1023: for (list = pack; list != NULL; list = next(list))
! 1024: {
! 1025: obj = OBJPTR(list);
! 1026:
! 1027: if (rnd(33) == 0) /* some stuff degrades */
! 1028: {
! 1029: if (obj->o_flags & ISBLESSED)
! 1030: obj->o_flags &= ~ISBLESSED;
! 1031: else
! 1032: obj->o_flags |= ISCURSED;
! 1033:
! 1034: msg("You feel nimble fingers reach into you pack.");
! 1035: }
! 1036:
! 1037: if ((obj != cur_armor &&
! 1038: obj != cur_weapon &&
! 1039: obj != cur_ring[LEFT_1] &&
! 1040: obj != cur_ring[LEFT_2] &&
! 1041: obj != cur_ring[LEFT_3] &&
! 1042: obj != cur_ring[LEFT_4] &&
! 1043: obj != cur_ring[LEFT_5] &&
! 1044: obj != cur_ring[RIGHT_1] &&
! 1045: obj != cur_ring[RIGHT_2] &&
! 1046: obj != cur_ring[RIGHT_3] &&
! 1047: obj != cur_ring[RIGHT_4] &&
! 1048: obj != cur_ring[RIGHT_5] &&
! 1049: !(obj->o_flags & ISPROT) &&
! 1050: is_magic(obj)
! 1051: || level > 45)
! 1052: && get_worth(obj) > worth)
! 1053: {
! 1054: stealit = list;
! 1055: worth = get_worth(obj);
! 1056: }
! 1057: }
! 1058:
! 1059: if (stealit != NULL)
! 1060: {
! 1061: struct object *newobj;
! 1062:
! 1063: newobj = OBJPTR(stealit);
! 1064:
! 1065: if (newobj->o_count > 1 && newobj->o_group == 0)
! 1066: {
! 1067: int oc;
! 1068: struct linked_list *nitem;
! 1069: struct object *op;
! 1070:
! 1071: oc = --(newobj->o_count);
! 1072: newobj->o_count = 1;
! 1073: nitem = new_item(sizeof *newobj);
! 1074: op = OBJPTR(nitem);
! 1075: *op = *newobj;
! 1076:
! 1077: msg("The %s stole %s!",mname,inv_name(newobj,LOWERCASE));
! 1078: newobj->o_count = oc;
! 1079: attach(mp->t_pack, nitem);
! 1080: }
! 1081: else
! 1082: {
! 1083: msg("The %s stole %s!",mname,inv_name(newobj,LOWERCASE));
! 1084: newobj->o_flags &= ~ISCURSED;
! 1085: dropcheck(newobj);
! 1086: rem_pack(newobj);
! 1087: attach(mp->t_pack, stealit);
! 1088:
! 1089: if (newobj->o_type == ARTIFACT)
! 1090: has_artifact &= ~(1 << newobj->o_which);
! 1091: }
! 1092:
! 1093: if (newobj->o_flags & ISOWNED)
! 1094: {
! 1095: turn_on(*mp, NOMOVE);
! 1096: msg("The %s is transfixed by your ownership spell.",
! 1097: mname);
! 1098: }
! 1099:
! 1100: if (rnd(2))
! 1101: turn_on(*mp, ISFLEE);
! 1102:
! 1103: turn_on(*mp, ISINVIS);
! 1104: updpack();
! 1105: }
! 1106: }
! 1107: }
! 1108: }
! 1109: else /* missed */
! 1110: {
! 1111: /* If the thing was trying to surprise, no good */
! 1112:
! 1113: if (on(*mp, CANSURPRISE))
! 1114: turn_off(*mp, CANSURPRISE);
! 1115:
! 1116: m_bounce(weapon, mname);
! 1117: }
! 1118:
! 1119: count = 0;
! 1120:
! 1121: status(FALSE);
! 1122:
! 1123: return(did_hit);
! 1124: }
! 1125:
! 1126:
! 1127: /*
! 1128: mon_mon_attack()
! 1129: A monster attacks another monster
! 1130: */
! 1131:
! 1132: int
! 1133: mon_mon_attack(struct thing *attacker, struct linked_list *mon, struct object *weapon, int thrown)
! 1134: {
! 1135: struct thing *attackee = THINGPTR(mon);
! 1136: int did_hit = FALSE;
! 1137: int ee_visible = cansee(attackee->t_pos.y, attackee->t_pos.x);
! 1138: int er_visible = cansee(attacker->t_pos.y, attacker->t_pos.x);
! 1139: char *mname1 = monsters[attacker->t_index].m_name;
! 1140: char *mname2 = monsters[attackee->t_index].m_name;
! 1141:
! 1142: /* Similar monsters don't hit each other */
! 1143:
! 1144: if (attacker->t_index == attackee->t_index)
! 1145: {
! 1146: if (fam_ptr && attacker == THINGPTR(fam_ptr) && er_visible)
! 1147: msg("Master, I cannot hit one of my brethren.");
! 1148: if (!thrown && rnd(100) - attacker->t_stats.s_charisma + luck < 0)
! 1149: {
! 1150: if (er_visible)
! 1151: msg("Your %s has made a new ally.", mname1);
! 1152:
! 1153: turn_on(*attackee, ISCHARMED);
! 1154: }
! 1155:
! 1156: return(FALSE);
! 1157: }
! 1158:
! 1159: /* stop running and any healing */
! 1160:
! 1161: attackee->t_rest_hpt = attackee->t_rest_pow = 0;
! 1162: attacker->t_rest_hpt = attacker->t_rest_pow = 0;
! 1163:
! 1164: if (roll_em(attacker, attackee, weapon, thrown,
! 1165: wield_weap(weapon, attacker)))
! 1166: {
! 1167: did_hit = TRUE;
! 1168:
! 1169: if (ee_visible && on(*attackee, CANSURPRISE))
! 1170: turn_off(*attackee, CANSURPRISE);
! 1171:
! 1172: if (ee_visible && er_visible && weapon != NULL)
! 1173: msg("The %s's %s hits the %s.", mname1,
! 1174: weaps[weapon->o_which].w_name, mname2);
! 1175: else if (ee_visible && er_visible)
! 1176: msg("The %s hits the %s.", mname1, mname2);
! 1177:
! 1178: if (attackee->t_stats.s_hpt <= 0)
! 1179: {
! 1180: killed(attacker, mon, MESSAGE,
! 1181: on(*attacker, ISFAMILIAR) ? POINTS : NOPOINTS);
! 1182: return(TRUE);
! 1183: }
! 1184: }
! 1185: else /* missed */
! 1186: {
! 1187: did_hit = FALSE;
! 1188:
! 1189: if (ee_visible && er_visible && weapon != NULL)
! 1190: msg("The %s's %s misses the %s.", mname1,
! 1191: weaps[weapon->o_which].w_name, mname2);
! 1192: else if (ee_visible && er_visible)
! 1193: msg("The %s misses the %s.", mname1, mname2);
! 1194: }
! 1195:
! 1196: if (er_visible && !ee_visible)
! 1197: msg("The %s struggles with something.",mname1);
! 1198:
! 1199: if (off(*attackee, ISMEAN) && off(*attackee, ISFAMILIAR))
! 1200: turn_on(*attackee, ISRUN);
! 1201:
! 1202: count = 0;
! 1203:
! 1204: status(FALSE);
! 1205:
! 1206: return(did_hit);
! 1207: }
! 1208:
! 1209:
! 1210: /*
! 1211: swing()
! 1212: returns true if the swing hits
! 1213: */
! 1214:
! 1215: int
! 1216: swing(int class, int at_lvl, int op_arm, int wplus)
! 1217: {
! 1218: int res = rnd(20) + 1;
! 1219: int need;
! 1220:
! 1221: need = att_mat[class].base -
! 1222: att_mat[class].factor *
! 1223: ((min(at_lvl, att_mat[class].max_lvl) -
! 1224: att_mat[class].offset) / att_mat[class].range) +
! 1225: (10 - op_arm);
! 1226:
! 1227: if (need > 20 && need <= 25)
! 1228: need = 20;
! 1229:
! 1230: return(res + wplus >= need);
! 1231: }
! 1232:
! 1233: /*
! 1234: init_exp()
! 1235: set up initial experience level change threshold
! 1236: */
! 1237:
! 1238: void
! 1239: init_exp(void)
! 1240: {
! 1241: max_stats.s_exp = e_levels[player.t_ctype];
! 1242: }
! 1243:
! 1244: /*
! 1245: next_exp_level()
! 1246: Do the next level arithmetic Returns number of levels to jump
! 1247: */
! 1248:
! 1249: int
! 1250: next_exp_level(int print_message)
! 1251: {
! 1252: int level_jump = 0;
! 1253:
! 1254: while (pstats.s_exp >= max_stats.s_exp)
! 1255: {
! 1256: pstats.s_exp -= max_stats.s_exp; /* excess experience points */
! 1257: level_jump++;
! 1258:
! 1259: if (max_stats.s_exp < 0x3fffffffL) /* 2^30 - 1 */
! 1260: max_stats.s_exp *= 2L; /* twice as many for next */
! 1261: }
! 1262:
! 1263: if (print_message)
! 1264: msg("You need %d more points to attain the %stitle of %s.",
! 1265: max_stats.s_exp - pstats.s_exp,
! 1266: (pstats.s_lvl > 14 ? "next " : ""),
! 1267: cnames[player.t_ctype][min(pstats.s_lvl, 14)]);
! 1268:
! 1269: return(level_jump);
! 1270: }
! 1271:
! 1272: /*
! 1273: check_level()
! 1274: Check to see if the guy has gone up a level.
! 1275: */
! 1276:
! 1277: void
! 1278: check_level(void)
! 1279: {
! 1280: int num_jumped, j, add;
! 1281: int nsides;
! 1282:
! 1283: if ((num_jumped = next_exp_level(NOMESSAGE)) <= 0)
! 1284: return;
! 1285:
! 1286: pstats.s_lvl += num_jumped; /* new experience level */
! 1287:
! 1288: switch (player.t_ctype)
! 1289: {
! 1290: case C_MAGICIAN:
! 1291: case C_ILLUSION: nsides = 4;
! 1292: break;
! 1293: case C_THIEF:
! 1294: case C_ASSASIN:
! 1295: case C_NINJA:
! 1296: case C_MONSTER:
! 1297: default: nsides = 6;
! 1298: break;
! 1299: case C_CLERIC:
! 1300: case C_DRUID: nsides = 8;
! 1301: break;
! 1302:
! 1303: case C_FIGHTER:
! 1304: case C_PALADIN:
! 1305: case C_RANGER:
! 1306: nsides = 12;
! 1307: break;
! 1308: }
! 1309:
! 1310: /* Take care of multi-level jumps */
! 1311:
! 1312: for (add = 0, j = 0; j < num_jumped; j++)
! 1313: {
! 1314: int increase = roll(1, nsides) + const_bonus();
! 1315:
! 1316: add += max(1, increase);
! 1317: }
! 1318:
! 1319: max_stats.s_hpt += add;
! 1320: pstats.s_hpt += add;
! 1321:
! 1322: msg("Welcome, %s, to level %d.",
! 1323: cnames[player.t_ctype][min(pstats.s_lvl - 1, 14)], pstats.s_lvl);
! 1324:
! 1325: next_exp_level(MESSAGE);
! 1326:
! 1327: /* Now add new spell points and learn new spells */
! 1328:
! 1329: nsides = 16 - nsides;
! 1330:
! 1331: for (add = 0, j = 0; j < num_jumped; j++)
! 1332: {
! 1333: int increase = roll(1, nsides) + int_wis_bonus();
! 1334:
! 1335: add += max(1, increase);
! 1336: }
! 1337:
! 1338: max_stats.s_power += add;
! 1339: pstats.s_power += add;
! 1340:
! 1341: learn_new_spells();
! 1342:
! 1343: /* Create a more powerful familiar (if player has one) */
! 1344:
! 1345: if (on(player, HASFAMILIAR) && on(player, CANSUMMON))
! 1346: summon_monster((short) 0, FAMILIAR, NOMESSAGE);
! 1347: }
! 1348:
! 1349: /*
! 1350: roll_em()
! 1351: Roll several attacks
! 1352: */
! 1353:
! 1354: int
! 1355: roll_em(struct thing *att_er, struct thing *def_er, struct object *weap, int thrown, struct object *my_weapon)
! 1356: {
! 1357: struct stats *att = &att_er->t_stats;
! 1358: struct stats *def = &def_er->t_stats;
! 1359: int ndice, nsides, nplus, def_arm;
! 1360: char *cp;
! 1361: int prop_hplus = 0, prop_dplus = 0;
! 1362: int is_player = (att_er == &player);
! 1363: int did_hit = FALSE;
! 1364:
! 1365: if (weap == NULL)
! 1366: cp = att->s_dmg;
! 1367: else if (!thrown)
! 1368: cp = weap->o_damage;
! 1369: else if ((weap->o_flags & ISMISL) && my_weapon != NULL &&
! 1370: my_weapon->o_which == weap->o_launch)
! 1371: {
! 1372: cp = weap->o_hurldmg;
! 1373: prop_hplus = my_weapon->o_hplus;
! 1374: prop_dplus = my_weapon->o_dplus;
! 1375: }
! 1376: else
! 1377: cp = (weap->o_flags & ISMISL ? weap->o_damage :
! 1378: weap->o_hurldmg);
! 1379:
! 1380: for (;;)
! 1381: {
! 1382: int damage;
! 1383: int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus);
! 1384: int dplus = prop_dplus + (weap == NULL ? 0 : weap->o_dplus);
! 1385:
! 1386: /* Is attacker weak? */
! 1387:
! 1388: if (on(*att_er, HASSTINK))
! 1389: hplus -= 2;
! 1390:
! 1391: if (is_player)
! 1392: {
! 1393: hplus += hitweight(); /* adjust for encumberence */
! 1394: dplus += hung_dam(); /* adjust damage for hungry player */
! 1395: dplus += ring_value(R_ADDDAM);
! 1396: }
! 1397:
! 1398: ndice = atoi(cp);
! 1399:
! 1400: if (cp == NULL || (cp = strchr(cp, 'd')) == NULL)
! 1401: break;
! 1402:
! 1403: nsides = atoi(++cp);
! 1404:
! 1405: if (cp != NULL && (cp = strchr(cp, '+')) != NULL)
! 1406: nplus = atoi(++cp);
! 1407: else
! 1408: nplus = 0;
! 1409:
! 1410: if (def == &pstats)
! 1411: {
! 1412: if (on(*att_er, NOMETAL) && cur_armor != NULL &&
! 1413: (cur_armor->o_which == RING_MAIL ||
! 1414: cur_armor->o_which == SCALE_MAIL ||
! 1415: cur_armor->o_which == CHAIN_MAIL ||
! 1416: cur_armor->o_which == SPLINT_MAIL ||
! 1417: cur_armor->o_which == BANDED_MAIL ||
! 1418: cur_armor->o_which == GOOD_CHAIN ||
! 1419: cur_armor->o_which == PLATE_MAIL ||
! 1420: cur_armor->o_which == PLATE_ARMOR))
! 1421: def_arm = def->s_arm;
! 1422: else if (cur_armor != NULL)
! 1423: def_arm = cur_armor->o_ac - 10 + pstats.s_arm;
! 1424: else
! 1425: def_arm = def->s_arm;
! 1426: def_arm -= ring_value(R_PROTECT);
! 1427: }
! 1428: else
! 1429: def_arm = def->s_arm;
! 1430:
! 1431: if ((weap != NULL && weap->o_type == WEAPON &&
! 1432: (weap->o_flags & ISSILVER) &&
! 1433: !save_throw(VS_MAGIC, def_er)) ||
! 1434: swing(att_er->t_ctype, att->s_lvl,
! 1435: def_arm - dext_prot(def->s_dext),
! 1436: hplus + str_plus(att->s_str) + dext_plus(att->s_dext)))
! 1437: {
! 1438: damage = roll(ndice, nsides) + dplus + nplus +
! 1439: add_dam(att->s_str);
! 1440:
! 1441: /* Rangers do +1/lvl vs. ISLARGE */
! 1442:
! 1443: if (att_er->t_ctype == C_RANGER && on(*def_er, ISLARGE))
! 1444: damage += pstats.s_lvl;
! 1445:
! 1446: /* Ninja do +1 per lvl/2 */
! 1447:
! 1448: if (att_er->t_ctype == C_NINJA)
! 1449: damage += pstats.s_lvl / 2;
! 1450:
! 1451: /* Check for half damage monsters */
! 1452:
! 1453: if (on(*def_er, HALFDAMAGE) && (weap != NULL) &&
! 1454: !((weap->o_flags & CANBURN) &&
! 1455: on(*def_er, CANBBURN)))
! 1456: damage /= 2;
! 1457:
! 1458: /* undead get twice damage from silver weapons */
! 1459:
! 1460: if (on(*def_er, ISUNDEAD) &&
! 1461: (weap != NULL) && (weap->o_flags & ISSILVER))
! 1462: damage *= 2;
! 1463:
! 1464: /* Check for fireproof monsters */
! 1465:
! 1466: if (on(*def_er, NOFIRE) && (weap != NULL) &&
! 1467: (weap->o_flags & CANBURN))
! 1468: damage = 0;
! 1469:
! 1470: /* Check for metal proof monsters */
! 1471:
! 1472: if (on(*def_er, NOMETAL) && (weap != NULL) &&
! 1473: (weap->o_flags & ISMETAL))
! 1474: damage = 0;
! 1475:
! 1476: /* Check for monsters that ignore sharp weapons */
! 1477:
! 1478: if (on(*def_er, NOSHARP) && (weap != NULL) &&
! 1479: (weap->o_flags & ISSHARP))
! 1480: damage = 0;
! 1481:
! 1482: /* Check for poisoned weapons */
! 1483:
! 1484: if ((weap != NULL) && (weap->o_flags & ISPOISON)
! 1485: && off(*def_er, ISUNDEAD)
! 1486: && !save_throw(VS_POISON, def_er))
! 1487: damage = max(damage, (def->s_hpt / 2) + 5);
! 1488:
! 1489: /* Check for no-damage and division */
! 1490:
! 1491: if (on(*def_er, BLOWDIVIDE) && rnd(3) == 0 &&
! 1492: !((weap != NULL) && (weap->o_flags & CANBURN)))
! 1493: {
! 1494: damage = 0;
! 1495: creat_mons(def_er, def_er->t_index, NOMESSAGE);
! 1496: }
! 1497:
! 1498: damage = max(0, damage);
! 1499:
! 1500: /*
! 1501: * sleeping monsters are backstabbed by certain
! 1502: * player classes, but only when they can see
! 1503: */
! 1504:
! 1505: if (is_player && !thrown && damage > 0 &&
! 1506: (off(*def_er, ISRUN) || def_er->t_no_move > 0) &&
! 1507: (player.t_ctype == C_THIEF ||
! 1508: player.t_ctype == C_NINJA ||
! 1509: player.t_ctype == C_ASSASIN) &&
! 1510: off(player,ISBLIND)
! 1511: && (wield_ok(&player, my_weapon, NOMESSAGE))
! 1512: && (wear_ok(&player, cur_armor, NOMESSAGE)))
! 1513: {
! 1514: damage *= (pstats.s_lvl / 4 + 2);
! 1515:
! 1516: msg("You backstabbed the %s %d times!",
! 1517: monsters[def_er->t_index].m_name,
! 1518: (pstats.s_lvl / 4) + 2);
! 1519:
! 1520: if (player.t_ctype == C_NINJA ||
! 1521: player.t_ctype == C_ASSASIN)
! 1522: pstats.s_exp += def_er->t_stats.s_exp
! 1523: / 2;
! 1524: }
! 1525:
! 1526: def->s_hpt -= damage; /* Do the damage */
! 1527:
! 1528: debug("Hit %s for %d (%d) ",
! 1529: monsters[def_er->t_index].m_name, damage,
! 1530: def_er->t_stats.s_hpt);
! 1531:
! 1532: if (is_player && is_wearing(R_VREGEN))
! 1533: {
! 1534: damage = (ring_value(R_VREGEN) * damage) / 3;
! 1535: pstats.s_hpt = min(max_stats.s_hpt,
! 1536: pstats.s_hpt + damage);
! 1537: }
! 1538:
! 1539: /* stun monsters when taking more than 1/3 their max hpts */
! 1540:
! 1541: if (is_player && !thrown && !did_hit &&
! 1542: (player.t_ctype == C_FIGHTER) &&
! 1543: (damage > def_er->maxstats.s_hpt / 3) )
! 1544: {
! 1545: if (def->s_hpt > 0)
! 1546: {
! 1547: msg("The %s has been stunned!",
! 1548: monsters[def_er->t_index].m_name);
! 1549: def_er->t_no_move += rnd(4) + 1;
! 1550: }
! 1551: pstats.s_exp += def_er->t_stats.s_exp / 4;
! 1552: }
! 1553:
! 1554: did_hit = TRUE;
! 1555: }
! 1556:
! 1557: if (cp == NULL || (cp = strchr(cp, '/')) == NULL)
! 1558: break;
! 1559:
! 1560: cp++;
! 1561: }
! 1562:
! 1563: return(did_hit);
! 1564: }
! 1565:
! 1566: /*
! 1567: prname()
! 1568: Figure out the monsters name
! 1569: */
! 1570:
! 1571: const char *
! 1572: prname(char *who)
! 1573: {
! 1574: if (on(player, ISBLIND))
! 1575: return(monstern);
! 1576: else
! 1577: return(who);
! 1578: }
! 1579:
! 1580: /*
! 1581: hit()
! 1582: Print a message to indicate a succesful hit
! 1583: */
! 1584:
! 1585: void
! 1586: hit(char *ee)
! 1587: {
! 1588: char *s;
! 1589:
! 1590: if (fighting)
! 1591: return;
! 1592:
! 1593: switch (rnd(15))
! 1594: {
! 1595: default: s = "hit"; break;
! 1596: case 1: s = "score an excellent hit on"; break;
! 1597: case 2: s = "injure"; break;
! 1598: case 3: s = "swing and hit"; break;
! 1599: case 4: s = "damage"; break;
! 1600: case 5: s = "barely nick"; break;
! 1601: case 6: s = "scratch"; break;
! 1602: case 7: s = "gouge a chunk out of"; break;
! 1603: case 8: s = "severely wound"; break;
! 1604: case 9: s = "counted coup on"; break;
! 1605: case 10: s = "drew blood from"; break;
! 1606: case 11: s = "nearly decapitate"; break;
! 1607: case 12: s = "deal a wacking great blow to"; break;
! 1608: }
! 1609:
! 1610: msg("You %s the %s.", s, prname(ee));
! 1611: }
! 1612:
! 1613: /*
! 1614: miss()
! 1615: Print a message to indicate a poor swing
! 1616: */
! 1617:
! 1618: void
! 1619: miss(char *ee)
! 1620: {
! 1621: char *s;
! 1622:
! 1623: if (fighting)
! 1624: return;
! 1625:
! 1626: switch (rnd(10))
! 1627: {
! 1628: default: s = "miss"; break;
! 1629: case 1: s = "swing and miss"; break;
! 1630: case 2: s = "barely miss"; break;
! 1631: case 3: s = "don't hit"; break;
! 1632: case 4: s = "wildly windmill around"; break;
! 1633: case 5: s = "almost fumble while missing"; break;
! 1634: }
! 1635:
! 1636: msg("You %s the %s.", s, prname(ee));
! 1637: }
! 1638:
! 1639: /*
! 1640: save_throw()
! 1641: See if a creature save against something
! 1642: */
! 1643:
! 1644: int
! 1645: save_throw(int which, struct thing *tp)
! 1646: {
! 1647: int need;
! 1648: int ring_bonus = 0;
! 1649: int armor_bonus = 0;
! 1650: int class_bonus = 0;
! 1651:
! 1652: if (tp == &player)
! 1653: {
! 1654: if (player.t_ctype == C_PALADIN)
! 1655: class_bonus = 2;
! 1656:
! 1657: ring_bonus = ring_value(R_PROTECT);
! 1658:
! 1659: if (cur_armor != NULL && (which == VS_WAND ||
! 1660: which == VS_MAGIC))
! 1661: {
! 1662: if (cur_armor->o_which == MITHRIL)
! 1663: armor_bonus += 5;
! 1664: armor_bonus += (armors[cur_armor->o_which].a_class
! 1665: - cur_armor->o_ac);
! 1666: }
! 1667: }
! 1668:
! 1669: need = 14 + which - tp->t_stats.s_lvl / 2 - ring_bonus -
! 1670: armor_bonus - class_bonus;
! 1671:
! 1672: /* Roll of 1 always fails; 20 always saves */
! 1673:
! 1674: if (need < 1)
! 1675: need = 1;
! 1676: else if (need > 20)
! 1677: need = 20;
! 1678:
! 1679: return(roll(1, 20) >= need);
! 1680: }
! 1681:
! 1682: /*
! 1683: save()
! 1684: See if he saves against various nasty things
! 1685: */
! 1686:
! 1687: int
! 1688: save(int which)
! 1689: {
! 1690: return save_throw(which, &player);
! 1691: }
! 1692:
! 1693: /*
! 1694: dext_plus()
! 1695: compute to-hit bonus for dexterity
! 1696: */
! 1697:
! 1698: int
! 1699: dext_plus(int dexterity)
! 1700: {
! 1701: return ((dexterity - 10) / 3);
! 1702: }
! 1703:
! 1704: /*
! 1705: * dext_prot: compute armor class bonus for dexterity
! 1706: */
! 1707:
! 1708: int
! 1709: dext_prot(int dexterity)
! 1710: {
! 1711: return ((dexterity - 9) / 2);
! 1712: }
! 1713:
! 1714: /*
! 1715: str_plus()
! 1716: compute bonus/penalties for strength on the "to hit" roll
! 1717: */
! 1718:
! 1719: static const int strtohit[] =
! 1720: {
! 1721: 0, 0, 0, -3, -2, -2, -1, -1,
! 1722: 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 1723: 1, 1, 3, 3, 4, 4, 5, 6, 7
! 1724: };
! 1725:
! 1726: int
! 1727: str_plus(int str)
! 1728: {
! 1729: int ret_val = str;
! 1730:
! 1731: if (str < 3)
! 1732: ret_val = 3;
! 1733: else if (str > 25)
! 1734: ret_val = 25;
! 1735:
! 1736: return(strtohit[ret_val]);
! 1737: }
! 1738:
! 1739: /*
! 1740: add_dam()
! 1741: compute additional damage done for exceptionally high or low strength
! 1742: */
! 1743:
! 1744: static const int str_damage[] =
! 1745: {
! 1746: 0, 0, 0, -1, -1, -1, 0, 0,
! 1747: 0, 0, 0, 0, 0, 0, 0, 0, 1,
! 1748: 1, 2, 7, 8, 9, 10, 11, 12, 14
! 1749: };
! 1750:
! 1751: int
! 1752: add_dam(int str)
! 1753: {
! 1754: int ret_val = str;
! 1755:
! 1756: if (str < 3)
! 1757: ret_val = 3;
! 1758: else if (str > 25)
! 1759: ret_val = 25;
! 1760:
! 1761: return(str_damage[ret_val]);
! 1762: }
! 1763:
! 1764: /*
! 1765: hung_dam()
! 1766: Calculate damage depending on players hungry state
! 1767: */
! 1768:
! 1769: int
! 1770: hung_dam(void)
! 1771: {
! 1772: int howmuch = 0;
! 1773:
! 1774: switch (hungry_state)
! 1775: {
! 1776: case F_OK:
! 1777: case F_HUNGRY: howmuch = 0; break;
! 1778: case F_WEAK: howmuch = -1; break;
! 1779: case F_FAINT: howmuch = -2; break;
! 1780: }
! 1781:
! 1782: return(howmuch);
! 1783: }
! 1784:
! 1785: /*
! 1786: raise_level()
! 1787: The guy just magically went up a level.
! 1788: */
! 1789:
! 1790: void
! 1791: raise_level(void)
! 1792: {
! 1793: pstats.s_exp = max_stats.s_exp;
! 1794: check_level();
! 1795: }
! 1796:
! 1797: /*
! 1798: thunk()
! 1799: A missile hits a monster
! 1800: */
! 1801:
! 1802: void
! 1803: thunk(struct object *weap, char *mname)
! 1804: {
! 1805: if (fighting)
! 1806: return;
! 1807:
! 1808: if (weap->o_type == WEAPON)
! 1809: msg("The %s hits the %s.", weaps[weap->o_which].w_name, prname(mname));
! 1810: else
! 1811: msg("You hit the %s.", prname(mname));
! 1812: }
! 1813:
! 1814: /*
! 1815: m_thunk()
! 1816: A missile from a monster hits the player
! 1817: */
! 1818:
! 1819: void
! 1820: m_thunk(struct object *weap, char *mname)
! 1821: {
! 1822: if (fighting)
! 1823: return;
! 1824:
! 1825: if (weap != NULL && weap->o_type == WEAPON)
! 1826: msg("The %s's %s hits you.",prname(mname),weaps[weap->o_which].w_name);
! 1827: else
! 1828: msg("The %s hits you.", prname(mname));
! 1829: }
! 1830:
! 1831: /*
! 1832: bounce()
! 1833: A missile misses a monster
! 1834: */
! 1835:
! 1836: void
! 1837: bounce(struct object *weap, char *mname)
! 1838: {
! 1839: if (fighting)
! 1840: return;
! 1841:
! 1842: if (weap->o_type == WEAPON)
! 1843: msg("The %s misses the %s.",weaps[weap->o_which].w_name,prname(mname));
! 1844: else
! 1845: msg("You missed the %s.", prname(mname));
! 1846: }
! 1847:
! 1848: /*
! 1849: m_bounce()
! 1850: A missile from a monster misses the player
! 1851: */
! 1852:
! 1853: void
! 1854: m_bounce(struct object *weap, char *mname)
! 1855: {
! 1856: if (fighting)
! 1857: return;
! 1858:
! 1859: if (weap != NULL && weap->o_type == WEAPON)
! 1860: msg("The %s's %s misses you.", prname(mname),
! 1861: weaps[weap->o_which].w_name);
! 1862: else
! 1863: msg("The %s misses you.", prname(mname));
! 1864: }
! 1865:
! 1866: /*
! 1867: remove_monster()
! 1868: remove a monster from the screen
! 1869: */
! 1870:
! 1871: void
! 1872: remove_monster(coord *mp, struct linked_list *item)
! 1873: {
! 1874: struct thing *tp = THINGPTR(item);
! 1875: char ch = tp->t_oldch;
! 1876:
! 1877: mvwaddch(mw, mp->y, mp->x, ' ');
! 1878:
! 1879: if (ch < 33 || ch == ' ')
! 1880: ch = CCHAR( mvwinch(stdscr, mp->y, mp->x) );
! 1881:
! 1882: if (cansee(mp->y, mp->x))
! 1883: mvwaddch(cw, mp->y, mp->x, ch);
! 1884:
! 1885: detach(mlist, item);
! 1886: discard(item);
! 1887: }
! 1888:
! 1889: /*
! 1890: is_magic()
! 1891: Returns true if an object radiates magic
! 1892: */
! 1893:
! 1894: int
! 1895: is_magic(struct object *obj)
! 1896: {
! 1897: switch (obj->o_type)
! 1898: {
! 1899: case ARMOR:
! 1900: return(obj->o_ac != armors[obj->o_which].a_class);
! 1901:
! 1902: case WEAPON:
! 1903: return(obj->o_hplus != 0 || obj->o_dplus != 0);
! 1904:
! 1905: case POTION:
! 1906: case SCROLL:
! 1907: case STICK:
! 1908: case RING:
! 1909: case ARTIFACT:
! 1910: return(TRUE);
! 1911: }
! 1912:
! 1913: return(FALSE);
! 1914: }
! 1915:
! 1916: /*
! 1917: killed()
! 1918: Called to put a monster to death
! 1919: */
! 1920:
! 1921: void
! 1922: killed(struct thing *killer, struct linked_list *item, int print_message,
! 1923: int give_points)
! 1924: {
! 1925: struct linked_list *pitem, *nitem;
! 1926: struct thing *tp = THINGPTR(item);
! 1927: int visible = cansee(tp->t_pos.y, tp->t_pos.x);
! 1928: int is_player = (killer == (&player));
! 1929:
! 1930: if (item == curr_mons)
! 1931: curr_mons = NULL;
! 1932: else if (item == next_mons)
! 1933: next_mons = next(next_mons);
! 1934:
! 1935: if (on(*tp, WASSUMMONED))
! 1936: {
! 1937: extinguish_fuse(FUSE_UNSUMMON);
! 1938: turn_off(player, HASSUMMONED);
! 1939: }
! 1940:
! 1941: if (print_message && visible)
! 1942: {
! 1943: if (is_player)
! 1944: addmsg("You have defeated ");
! 1945: else
! 1946: addmsg("The %s has defeated ",
! 1947: monsters[killer->t_index].m_name);
! 1948:
! 1949: if (on(player, ISBLIND))
! 1950: msg("it.");
! 1951: else
! 1952: msg("the %s.", monsters[tp->t_index].m_name);
! 1953: }
! 1954: debug("Removing %s", monsters[tp->t_index].m_name);
! 1955: if (killer != NULL && item == fam_ptr) /* The player's familiar died */
! 1956: {
! 1957: turn_off(player, HASFAMILIAR);
! 1958: fam_ptr = NULL;
! 1959: msg("An incredible wave of sadness sweeps over you.");
! 1960: }
! 1961:
! 1962: check_residue(tp);
! 1963:
! 1964: if (is_player)
! 1965: {
! 1966: fighting = FALSE;
! 1967:
! 1968: if (on(*tp, ISFRIENDLY))
! 1969: {
! 1970: msg("You feel a slight chill run up and down your spine.");
! 1971: luck++;
! 1972: }
! 1973: }
! 1974:
! 1975: if (give_points)
! 1976: {
! 1977: if (killer != NULL)
! 1978: {
! 1979: killer->t_stats.s_exp += tp->t_stats.s_exp;
! 1980:
! 1981: if (on(*killer, ISFAMILIAR))
! 1982: pstats.s_exp += tp->t_stats.s_exp;
! 1983: }
! 1984:
! 1985: if (is_player)
! 1986: {
! 1987: switch (player.t_ctype)
! 1988: {
! 1989: case C_CLERIC:
! 1990: case C_PALADIN:
! 1991: if (on(*tp, ISUNDEAD) || on(*tp, ISUNIQUE))
! 1992: {
! 1993: pstats.s_exp += tp->t_stats.s_exp / 2;
! 1994: msg("You are to be commended for smiting the ungodly.");
! 1995: }
! 1996: break;
! 1997:
! 1998: case C_DRUID:
! 1999: case C_RANGER:
! 2000: if (on(*tp, ISLARGE))
! 2001: {
! 2002: pstats.s_exp += tp->t_stats.s_exp / 2;
! 2003: msg("Congratulations on smiting a dangerous monster.");
! 2004: }
! 2005: break;
! 2006:
! 2007: case C_MAGICIAN:
! 2008: case C_ILLUSION:
! 2009: if (on(*tp, DRAINBRAIN))
! 2010: {
! 2011: pstats.s_exp += tp->t_stats.s_exp / 2;
! 2012: msg("Congratulations on smiting a dangerous monster.");
! 2013: }
! 2014:
! 2015: }
! 2016: }
! 2017: check_level();
! 2018: }
! 2019:
! 2020: /* Empty the monsters pack */
! 2021:
! 2022: for (pitem = tp->t_pack; pitem != NULL; pitem = nitem)
! 2023: {
! 2024: struct object *obj = OBJPTR(pitem);
! 2025:
! 2026: nitem = next(pitem);
! 2027:
! 2028: obj->o_pos = tp->t_pos;
! 2029: detach(tp->t_pack, pitem);
! 2030:
! 2031: if (killer == NULL)
! 2032: discard(pitem);
! 2033: else
! 2034: fall(killer, pitem, FALSE, FALSE);
! 2035: }
! 2036:
! 2037: remove_monster(&tp->t_pos, item);
! 2038: }
! 2039:
! 2040:
! 2041: /*
! 2042: wield_weap()
! 2043: Returns a pointer to the weapon the monster is wielding corresponding to the given thrown weapon
! 2044: */
! 2045:
! 2046: struct object *
! 2047: wield_weap(struct object *weapon, struct thing *mp)
! 2048: {
! 2049: int look_for;
! 2050: struct linked_list *pitem;
! 2051:
! 2052: if (weapon == NULL)
! 2053: return (NULL);
! 2054:
! 2055: switch (weapon->o_which)
! 2056: {
! 2057: case BOLT:
! 2058: look_for = CROSSBOW;
! 2059: break;
! 2060:
! 2061: case ARROW:
! 2062: look_for = BOW;
! 2063: break;
! 2064:
! 2065: case SILVERARROW:
! 2066: case FLAMEARROW:
! 2067: look_for = BOW;
! 2068: break;
! 2069:
! 2070: case ROCK:
! 2071: case BULLET:
! 2072: look_for = SLING;
! 2073: break;
! 2074:
! 2075: default:
! 2076: return(NULL);
! 2077: }
! 2078:
! 2079: for (pitem = mp->t_pack; pitem; pitem = next(pitem))
! 2080: if ((OBJPTR(pitem))->o_which == look_for)
! 2081: return(OBJPTR(pitem));
! 2082:
! 2083: return (NULL);
! 2084: }
! 2085:
! 2086: /*
! 2087: summon_help()
! 2088: Summon - see whether to summon help Returns TRUE if help comes, FALSE
! 2089: otherwise
! 2090: */
! 2091:
! 2092: void
! 2093: summon_help(struct thing *mons, int force)
! 2094: {
! 2095: char *helpname;
! 2096: int which, i;
! 2097: char *mname = monsters[mons->t_index].m_name;
! 2098:
! 2099: /* Try to summon if less than 1/3 max hit points */
! 2100:
! 2101: if (on(*mons, CANSUMMON) &&
! 2102: (force == FORCE ||
! 2103: (mons->t_stats.s_hpt < mons->maxstats.s_hpt / 3) &&
! 2104: (rnd(40 * 10) < (mons->t_stats.s_lvl * mons->t_stats.s_intel))))
! 2105: {
! 2106: turn_off(*mons, CANSUMMON);
! 2107: msg("The %s summons its attendants!", mname);
! 2108: helpname = monsters[mons->t_index].m_typesum;
! 2109:
! 2110: for (which = 1; which < nummonst; which++)
! 2111: {
! 2112: if (strcmp(helpname, monsters[which].m_name) == 0)
! 2113: break;
! 2114: }
! 2115:
! 2116: if (which >= nummonst)
! 2117: {
! 2118: debug("Couldn't find summoned one.");
! 2119: return;
! 2120: }
! 2121:
! 2122: /* summoned monster was genocided */
! 2123:
! 2124: if (!monsters[which].m_normal)
! 2125: {
! 2126: msg("The %s becomes very annoyed at you!", mname);
! 2127:
! 2128: if (on(*mons, ISSLOW))
! 2129: turn_off(*mons, ISSLOW);
! 2130: else
! 2131: turn_on(*mons, ISHASTE);
! 2132:
! 2133: return;
! 2134: }
! 2135: else
! 2136: for (i = 0; i < monsters[mons->t_index].m_numsum; i++)
! 2137: {
! 2138: struct linked_list *ip;
! 2139: struct thing *tp;
! 2140:
! 2141: if ((ip = creat_mons(mons, which, NOMESSAGE)) != NULL)
! 2142: {
! 2143: tp = THINGPTR(ip);
! 2144: turn_off(*tp, ISFRIENDLY);
! 2145: }
! 2146: }
! 2147: }
! 2148:
! 2149: return;
! 2150: }
! 2151:
! 2152: /*
! 2153: maxdamage()
! 2154: return the max damage a weapon can do
! 2155: */
! 2156:
! 2157: int
! 2158: maxdamage(char *cp)
! 2159: {
! 2160: int ndice, nsides, nplus;
! 2161:
! 2162: ndice = atoi(cp);
! 2163:
! 2164: if (cp == NULL || (cp = strchr(cp, 'd')) == NULL)
! 2165: return(0);
! 2166:
! 2167: nsides = atoi(++cp);
! 2168:
! 2169: if (cp != NULL && (cp = strchr(cp, '+')) != NULL)
! 2170: nplus = atoi(++cp);
! 2171: else
! 2172: nplus = 0;
! 2173:
! 2174: return(ndice * nsides + nplus);
! 2175: }
CVSweb