Annotation of early-roguelike/arogue5/fight.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * All the fighting gets done here
! 3: *
! 4: * Advanced Rogue
! 5: * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
! 6: * All rights reserved.
! 7: *
! 8: * Based on "Rogue: Exploring the Dungeons of Doom"
! 9: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 10: * All rights reserved.
! 11: *
! 12: * See the file LICENSE.TXT for full copyright and licensing information.
! 13: */
! 14:
! 15: #include "curses.h"
! 16: #include <stdlib.h>
! 17: #include <ctype.h>
! 18: #include <string.h>
! 19: #include "rogue.h"
! 20:
! 21: bool roll_em(struct thing *att_er, struct thing *def_er, struct object *weap,
! 22: bool hurl, struct object *cur_weapon, bool back_stab);
! 23: void hit(struct object *weapon, struct thing *tp, const char *er,
! 24: const char *ee, bool back_stab);
! 25: void miss(struct object *weapon, struct thing *tp, const char *er,
! 26: const char *ee);
! 27: int dext_plus(int dexterity);
! 28: int str_plus(short str);
! 29: int add_dam(short str);
! 30: int hung_dam(void);
! 31: void thunk(struct object *weap, struct thing *tp, const char *mname);
! 32: void m_thunk(struct object *weap, struct thing *tp, const char *mname);
! 33: void bounce(struct object *weap, struct thing *tp, const char *mname);
! 34: void m_bounce(struct object *weap, struct thing *tp, const char *mname);
! 35: struct object *wield_weap(struct object *thrown, struct thing *mp);
! 36: void explode(struct thing *tp);
! 37:
! 38: #define CONF_DAMAGE -1
! 39: #define PARAL_DAMAGE -2
! 40: #define DEST_DAMAGE -3
! 41:
! 42: static const struct matrix att_mat[5] = {
! 43: /* Base Max_lvl, Factor, Offset, Range */
! 44: { 10, 25, 2, 1, 2 },
! 45: { 9, 18, 2, 1, 5 },
! 46: { 10, 19, 2, 1, 3 },
! 47: { 10, 21, 2, 1, 4 },
! 48: { 7, 25, 1, 0, 2 }
! 49: };
! 50:
! 51: /*
! 52: * fight:
! 53: * The player attacks the monster.
! 54: */
! 55:
! 56: bool
! 57: fight(coord *mp, struct object *weap, bool thrown)
! 58: {
! 59: register struct thing *tp;
! 60: register struct linked_list *item;
! 61: register bool did_hit = TRUE;
! 62: bool back_stab = FALSE;
! 63:
! 64: /*
! 65: * Find the monster we want to fight
! 66: */
! 67: if ((item = find_mons(mp->y, mp->x)) == NULL) {
! 68: return(FALSE); /* must have killed him already */
! 69: }
! 70: tp = THINGPTR(item);
! 71: /*
! 72: * Since we are fighting, things are not quiet so no healing takes
! 73: * place.
! 74: */
! 75: player.t_quiet = 0;
! 76: tp->t_quiet = 0;
! 77:
! 78: /*
! 79: * if its in the wall, we can't hit it
! 80: */
! 81: if (on(*tp, ISINWALL) && off(player, CANINWALL))
! 82: return(FALSE);
! 83:
! 84: /*
! 85: * Let him know it was really a mimic (if it was one).
! 86: */
! 87: if (on(*tp, ISDISGUISE) && (tp->t_type != tp->t_disguise) &&
! 88: off(player, ISBLIND))
! 89: {
! 90: msg("Wait! That's a %s!", monsters[tp->t_index].m_name);
! 91: turn_off(*tp, ISDISGUISE);
! 92: did_hit = thrown;
! 93: }
! 94: if (on(*tp, CANSURPRISE) && off(player, ISBLIND) && !ISWEARING(R_ALERT)) {
! 95: msg("Wait! There's a %s!", monsters[tp->t_index].m_name);
! 96: turn_off(*tp, CANSURPRISE);
! 97: did_hit = thrown;
! 98: }
! 99: /*
! 100: * if he's a thief and the creature is asleep then he gets a chance
! 101: * for a backstab
! 102: */
! 103: if (player.t_ctype == C_THIEF &&
! 104: (!on(*tp, ISRUN) || on(*tp, ISHELD) || tp->t_no_move > 0)&&
! 105: !on(*tp, NOSTAB))
! 106: back_stab = TRUE;
! 107:
! 108: runto(tp, &hero);
! 109:
! 110: if (did_hit)
! 111: {
! 112: register const char *mname;
! 113:
! 114: did_hit = FALSE;
! 115: mname = (on(player, ISBLIND)) ? "it" : monsters[tp->t_index].m_name;
! 116: if (!can_blink(tp) &&
! 117: ( ((weap != NULL) && (weap->o_type == RELIC)) ||
! 118: ((off(*tp, MAGICHIT) || ((weap != NULL) && (weap->o_hplus > 0 || weap->o_dplus > 0)) ) &&
! 119: (off(*tp, BMAGICHIT) || ((weap != NULL) && (weap->o_hplus > 1 || weap->o_dplus > 1)) ) &&
! 120: (off(*tp, CMAGICHIT) || ((weap != NULL) && (weap->o_hplus > 2 || weap->o_dplus > 2)) ) ) )
! 121: && roll_em(&player, tp, weap, thrown, cur_weapon, back_stab))
! 122: {
! 123: did_hit = TRUE;
! 124:
! 125: if (on(*tp, NOMETAL) && weap != NULL &&
! 126: weap->o_type != RELIC && weap->o_flags & ISMETAL) {
! 127: sprintf(outstring,"Your %s passes right through the %s!",
! 128: weaps[weap->o_which].w_name, mname);
! 129: msg(outstring);
! 130: }
! 131: else if (thrown) {
! 132: tp->t_wasshot = TRUE;
! 133: thunk(weap, tp, mname);
! 134: }
! 135: else
! 136: hit(weap, tp, NULL, mname, back_stab);
! 137:
! 138: /* If the player hit a rust monster, he better have a + weapon */
! 139: if (on(*tp, CANRUST) && !thrown && (weap != NULL) &&
! 140: weap->o_type != RELIC &&
! 141: (weap->o_flags & ISMETAL) &&
! 142: !(weap->o_flags & ISPROT) &&
! 143: (weap->o_hplus < 1) && (weap->o_dplus < 1)) {
! 144: if (rnd(100) < 50) weap->o_hplus--;
! 145: else weap->o_dplus--;
! 146: msg(terse ? "Your %s weakens!"
! 147: : "Your %s appears to be weaker now!",
! 148: weaps[weap->o_which].w_name);
! 149: }
! 150:
! 151: /* If the player hit something that shrieks, wake the dungeon */
! 152: if (on(*tp, CANSHRIEK)) {
! 153: turn_off(*tp, CANSHRIEK);
! 154: msg("The %s emits a piercing shriek.", mname);
! 155: aggravate();
! 156: }
! 157:
! 158: /* If the player hit something that can surprise, it can't now */
! 159: if (on(*tp, CANSURPRISE)) turn_off(*tp, CANSURPRISE);
! 160:
! 161:
! 162: /*
! 163: * Can the player confuse?
! 164: */
! 165: if (on(player, CANHUH) && !thrown) {
! 166: msg("Your hands stop glowing red");
! 167: msg("The %s appears confused.", mname);
! 168: turn_on(*tp, ISHUH);
! 169: turn_off(player, CANHUH);
! 170: }
! 171: /*
! 172: * does the creature explode when hit?
! 173: */
! 174: if (on(*tp, CANEXPLODE))
! 175: explode(tp);
! 176:
! 177: /*
! 178: * Merchants just disappear if hit
! 179: */
! 180: if (on(*tp, CANSELL)) {
! 181: msg("The %s disappears with his wares in a flash.",mname);
! 182: killed(item, FALSE, FALSE);
! 183: }
! 184:
! 185: else if (tp->t_stats.s_hpt <= 0)
! 186: killed(item, TRUE, TRUE);
! 187:
! 188: /* If the monster is fairly intelligent and about to die, it
! 189: * may turn tail and run.
! 190: */
! 191: else if ((tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/10)) &&
! 192: (rnd(25) < tp->t_stats.s_intel)) {
! 193: turn_on(*tp, ISFLEE);
! 194:
! 195: /* If monster was suffocating, stop it */
! 196: if (on(*tp, DIDSUFFOCATE)) {
! 197: turn_off(*tp, DIDSUFFOCATE);
! 198: extinguish(suffocate);
! 199: }
! 200:
! 201: /* If monster held us, stop it */
! 202: if (on(*tp, DIDHOLD) && (--hold_count == 0))
! 203: turn_off(player, ISHELD);
! 204: turn_off(*tp, DIDHOLD);
! 205: }
! 206: }
! 207: else {
! 208: if (thrown)
! 209: bounce(weap, tp, mname);
! 210: else
! 211: miss(weap, tp, NULL, mname);
! 212: }
! 213: }
! 214: count = 0;
! 215: return did_hit;
! 216: }
! 217:
! 218: /*
! 219: * attack:
! 220: * The monster attacks the player
! 221: */
! 222:
! 223: bool
! 224: attack(struct thing *mp, struct object *weapon, bool thrown)
! 225: {
! 226: register const char *mname;
! 227: register bool did_hit = FALSE;
! 228: register struct object *wielded; /* The wielded weapon */
! 229:
! 230: /*
! 231: * Since this is an attack, stop running and any healing that was
! 232: * going on at the time.
! 233: */
! 234: running = FALSE;
! 235: player.t_quiet = 0;
! 236: mp->t_quiet = 0;
! 237:
! 238: if (on(*mp, ISDISGUISE) && off(player, ISBLIND))
! 239: turn_off(*mp, ISDISGUISE);
! 240: mname = on(player, ISBLIND) ? "it" : monsters[mp->t_index].m_name;
! 241:
! 242: /*
! 243: * Try to find a weapon to wield. Wield_weap will return a
! 244: * projector if weapon is a projectile (eg. bow for arrow).
! 245: * If weapon is NULL, it will try to find a suitable weapon.
! 246: */
! 247: wielded = wield_weap(weapon, mp);
! 248: if (weapon == NULL) weapon = wielded;
! 249:
! 250: if (roll_em(mp, &player, weapon, thrown, wielded, FALSE)) {
! 251: did_hit = TRUE;
! 252:
! 253: if (thrown) m_thunk(weapon, mp, mname);
! 254: else hit(weapon, mp, mname, NULL, FALSE);
! 255:
! 256: if (pstats.s_hpt <= 0)
! 257: death(mp->t_index); /* Bye bye life ... */
! 258:
! 259: /*
! 260: * suprising monsters appear after they shoot at you
! 261: */
! 262: if (thrown) {
! 263: if (on(*mp, CANSURPRISE))
! 264: turn_off(*mp, CANSURPRISE);
! 265: }
! 266: if (!thrown) {
! 267: /*
! 268: * If a vampire hits, it may take half your hit points
! 269: */
! 270: if (on(*mp, CANSUCK) && !save(VS_MAGIC, &player, 0)) {
! 271: if (pstats.s_hpt == 1) death(mp->t_index);
! 272: else {
! 273: pstats.s_hpt /= 2;
! 274: msg("You feel your life force being drawn from you.");
! 275: }
! 276: }
! 277:
! 278: /*
! 279: * Stinking monsters make player weaker (to hit)
! 280: */
! 281: if (on(*mp, CANSTINK)) {
! 282: turn_off(*mp, CANSTINK);
! 283: if (!save(VS_POISON, &player, 0)) {
! 284: msg("The stench of the %s sickens you.", mname);
! 285: if (on(player, HASSTINK)) lengthen(unstink, STINKTIME);
! 286: else {
! 287: turn_on(player, HASSTINK);
! 288: fuse(unstink, 0, STINKTIME, AFTER);
! 289: }
! 290: }
! 291: }
! 292:
! 293: /*
! 294: * Chilling monster reduces strength each time
! 295: */
! 296: if (on(*mp, CANCHILL)) {
! 297: if (!ISWEARING(R_SUSABILITY) && !save(VS_POISON, &player, 0)) {
! 298: msg("You cringe at the %s's chilling touch.", mname);
! 299: chg_str(-1);
! 300: if (lost_str++ == 0)
! 301: fuse(res_strength, 0, CHILLTIME, AFTER);
! 302: else lengthen(res_strength, CHILLTIME);
! 303: }
! 304: }
! 305:
! 306: /*
! 307: * itching monsters reduce dexterity (temporarily)
! 308: */
! 309: if (on(*mp, CANITCH) && !save(VS_POISON, &player, 0)) {
! 310: msg("The claws of the %s scratch you", mname);
! 311: if(ISWEARING(R_SUSABILITY)) {
! 312: msg("The scratch has no effect");
! 313: }
! 314: else {
! 315: turn_on(player, HASITCH);
! 316: add_dexterity(TRUE);
! 317: lost_dext++;
! 318: fuse(un_itch, 0, roll(HEALTIME,SICKTIME), AFTER);
! 319: }
! 320: }
! 321:
! 322:
! 323: /*
! 324: * If a hugging monster hits, it may SQUEEEEEEEZE
! 325: */
! 326: if (on(*mp, CANHUG)) {
! 327: if (roll(1,20) >= 18 || roll(1,20) >= 18) {
! 328: msg("The %s squeezes you against itself.", mname);
! 329: if ((pstats.s_hpt -= roll(2,8)) <= 0)
! 330: death(mp->t_index);
! 331: }
! 332: }
! 333:
! 334: /*
! 335: * If a disease-carrying monster hits, there is a chance the
! 336: * player will catch the disease
! 337: */
! 338: if (on(*mp, CANDISEASE) &&
! 339: (rnd(pstats.s_const) < mp->t_stats.s_lvl) &&
! 340: off(player, HASDISEASE)) {
! 341: if (ISWEARING(R_HEALTH)) msg("The wound heals quickly.");
! 342: else {
! 343: turn_on(player, HASDISEASE);
! 344: fuse(cure_disease, 0, roll(HEALTIME,SICKTIME), AFTER);
! 345: msg(terse ? "You have been diseased."
! 346: : "You have contracted a disease!");
! 347: }
! 348: }
! 349:
! 350: /*
! 351: * If a rust monster hits, you lose armor
! 352: */
! 353: if (on(*mp, CANRUST)) {
! 354: if (cur_armor != NULL &&
! 355: cur_armor->o_which != LEATHER &&
! 356: cur_armor->o_which != STUDDED_LEATHER &&
! 357: cur_armor->o_which != PADDED_ARMOR &&
! 358: !(cur_armor->o_flags & ISPROT) &&
! 359: cur_armor->o_ac < pstats.s_arm+1 ) {
! 360: msg(terse ? "Your armor weakens"
! 361: : "Your armor appears to be weaker now. Oh my!");
! 362: cur_armor->o_ac++;
! 363: }
! 364: if (cur_misc[WEAR_BRACERS] != NULL &&
! 365: cur_misc[WEAR_BRACERS]->o_ac > 0 &&
! 366: !(cur_misc[WEAR_BRACERS]->o_flags & ISPROT)) {
! 367: cur_misc[WEAR_BRACERS]->o_ac--;
! 368: if (cur_misc[WEAR_BRACERS]->o_ac == 0) {
! 369: register struct linked_list *item;
! 370:
! 371: for (item=pack; item!=NULL; item=next(item)) {
! 372: if (OBJPTR(item) == cur_misc[WEAR_BRACERS]) {
! 373: detach(pack, item);
! 374: o_discard(item);
! 375: break;
! 376: }
! 377: }
! 378: msg ("Your bracers crumble and fall off!");
! 379: cur_misc[WEAR_BRACERS] = NULL;
! 380: inpack--;
! 381: }
! 382: else {
! 383: msg("Your bracers weaken!");
! 384: }
! 385: }
! 386: }
! 387: /*
! 388: * If can dissolve and hero has leather type armor
! 389: */
! 390: if (on(*mp, CANDISSOLVE) && cur_armor != NULL &&
! 391: (cur_armor->o_which == LEATHER ||
! 392: cur_armor->o_which == STUDDED_LEATHER ||
! 393: cur_armor->o_which == PADDED_ARMOR) &&
! 394: !(cur_armor->o_flags & ISPROT) &&
! 395: cur_armor->o_ac < pstats.s_arm+1) {
! 396: msg(terse ? "Your armor dissolves"
! 397: : "Your armor appears to dissolve. Oh my!");
! 398: cur_armor->o_ac++;
! 399: }
! 400:
! 401: /* If a surprising monster hit you, you can see it now */
! 402: if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
! 403:
! 404: /*
! 405: * If an infesting monster hits you, you get a parasite or rot
! 406: */
! 407: if (on(*mp, CANINFEST) && rnd(pstats.s_const) < mp->t_stats.s_lvl) {
! 408: if (ISWEARING(R_HEALTH)) msg("The wound quickly heals.");
! 409: else {
! 410: turn_off(*mp, CANINFEST);
! 411: msg(terse ? "You have been infested."
! 412: : "You have contracted a parasitic infestation!");
! 413: infest_dam++;
! 414: turn_on(player, HASINFEST);
! 415: }
! 416: }
! 417:
! 418: /*
! 419: * Ants have poisonous bites
! 420: */
! 421: if (on(*mp, CANPOISON) && !save(VS_POISON, &player, 0)) {
! 422: if (ISWEARING(R_SUSABILITY))
! 423: msg(terse ? "Sting has no effect"
! 424: : "A sting momentarily weakens you");
! 425: else {
! 426: chg_str(-1);
! 427: msg(terse ? "A sting has weakened you" :
! 428: "You feel a sting in your arm and now feel weaker");
! 429: }
! 430: }
! 431: /*
! 432: * does it take wisdom away?
! 433: */
! 434: if (on(*mp, TAKEWISDOM) &&
! 435: !save(VS_MAGIC, &player, 0) &&
! 436: !ISWEARING(R_SUSABILITY)) {
! 437: add_wisdom(TRUE);
! 438: }
! 439: /*
! 440: * does it take intelligence away?
! 441: */
! 442: if (on(*mp, TAKEINTEL) &&
! 443: !save(VS_MAGIC, &player, 0) &&
! 444: !ISWEARING(R_SUSABILITY)) {
! 445: add_intelligence(TRUE);
! 446: }
! 447: /*
! 448: * Cause fear by touching
! 449: */
! 450: if (on(*mp, TOUCHFEAR)) {
! 451: turn_off(*mp, TOUCHFEAR);
! 452: if (!ISWEARING(R_HEROISM) &&
! 453: !save(VS_WAND, &player, 0) &&
! 454: !(on(player, ISFLEE) && (player.t_dest == &mp->t_pos))) {
! 455: turn_on(player, ISFLEE);
! 456: player.t_dest = &mp->t_pos;
! 457: msg("The %s's touch terrifies you.", mname);
! 458: }
! 459: }
! 460:
! 461: /*
! 462: * make the hero dance (as in otto's irresistable dance)
! 463: */
! 464: if (on(*mp, CANDANCE) &&
! 465: !on(player, ISDANCE) &&
! 466: !save(VS_MAGIC, &player, -4)) {
! 467: turn_off(*mp, CANDANCE);
! 468: turn_on(player, ISDANCE);
! 469: msg("You begin to dance uncontrollably!");
! 470: fuse(undance, 0, roll(2,4), AFTER);
! 471: }
! 472:
! 473: /*
! 474: * Suffocating our hero
! 475: */
! 476: if (on(*mp, CANSUFFOCATE) && (rnd(100) < 15) &&
! 477: (find_slot(suffocate) == FALSE)) {
! 478: turn_on(*mp, DIDSUFFOCATE);
! 479: msg("The %s is beginning to suffocate you.", mname);
! 480: fuse(suffocate, 0, roll(4,2), AFTER);
! 481: }
! 482:
! 483: /*
! 484: * Turning to stone
! 485: */
! 486: if (on(*mp, TOUCHSTONE)) {
! 487: turn_off(*mp, TOUCHSTONE);
! 488: if (on(player, CANINWALL))
! 489: msg("The %s's touch has no effect.", mname);
! 490: else {
! 491: if (!save(VS_PETRIFICATION, &player, 0) && rnd(100) < 15) {
! 492: msg("Your body begins to solidify.");
! 493: msg("You are turned to stone !!! --More--");
! 494: wait_for(cw,' ');
! 495: death(D_PETRIFY);
! 496: }
! 497: else {
! 498: msg("The %s's touch stiffens your limbs.", mname);
! 499: no_command += STONETIME;
! 500: }
! 501: }
! 502: }
! 503:
! 504: /*
! 505: * Wraiths might drain energy levels
! 506: */
! 507: if ((on(*mp, CANDRAIN) || on(*mp, DOUBLEDRAIN)) && rnd(100) < 15) {
! 508: lower_level(mp->t_index);
! 509: if (on(*mp, DOUBLEDRAIN)) lower_level(mp->t_index);
! 510: turn_on(*mp, DIDDRAIN);
! 511: }
! 512:
! 513: /*
! 514: * Violet fungi stops the poor guy from moving
! 515: */
! 516: if (on(*mp, CANHOLD) && off(*mp, DIDHOLD)) {
! 517: turn_on(player, ISHELD);
! 518: turn_on(*mp, DIDHOLD);
! 519: hold_count++;
! 520: }
! 521:
! 522: /*
! 523: * Sucker will suck blood and run
! 524: */
! 525: if (on(*mp, CANDRAW)) {
! 526: turn_off(*mp, CANDRAW);
! 527: turn_on(*mp, ISFLEE);
! 528: msg("The %s sates itself with your blood.", mname);
! 529: if ((pstats.s_hpt -= 12) <= 0) death(mp->t_index);
! 530: }
! 531:
! 532: /*
! 533: * Bad smell will force a reduction in strength
! 534: */
! 535: if (on(*mp, CANSMELL)) {
! 536: turn_off(*mp, CANSMELL);
! 537: if (save(VS_MAGIC, &player, 0) || ISWEARING(R_SUSABILITY))
! 538: msg("You smell an unpleasant odor.");
! 539: else {
! 540: int odor_str = -(rnd(6)+1);
! 541:
! 542: msg("You are overcome by a foul odor.");
! 543: if (lost_str == 0) {
! 544: chg_str(odor_str);
! 545: fuse(res_strength, 0, SMELLTIME, AFTER);
! 546: lost_str -= odor_str;
! 547: }
! 548: else lengthen(res_strength, SMELLTIME);
! 549: }
! 550: }
! 551:
! 552: /*
! 553: * Paralyzation
! 554: */
! 555: if (on(*mp, CANPARALYZE)) {
! 556: turn_off(*mp, CANPARALYZE);
! 557: if (!save(VS_PARALYZATION, &player, 0)) {
! 558: if (on(player, CANINWALL))
! 559: msg("The %s's touch has no effect.", mname);
! 560: else {
! 561: msg("The %s's touch paralyzes you.", mname);
! 562: no_command += FREEZETIME;
! 563: }
! 564: }
! 565: }
! 566:
! 567: /*
! 568: * Painful wounds make you faint
! 569: */
! 570: if (on(*mp, CANPAIN)) {
! 571: turn_off(*mp, CANPAIN);
! 572: if (!ISWEARING(R_ALERT) && !save(VS_POISON, &player, 0)) {
! 573: msg("You faint from the painful wound");
! 574: no_command += PAINTIME;
! 575: }
! 576: }
! 577:
! 578: /*
! 579: * The monsters touch slows the hero down
! 580: */
! 581: if (on(*mp, CANSLOW)) {
! 582: turn_off(*mp, CANSLOW);
! 583: if (!save(VS_PARALYZATION, &player, 0))
! 584: add_slow();
! 585: }
! 586:
! 587: /*
! 588: * Rotting
! 589: */
! 590: if (on(*mp, CANROT)) {
! 591: if (!ISWEARING(R_HEALTH) &&
! 592: !save(VS_POISON, &player, 0) &&
! 593: off(player, DOROT)) {
! 594: turn_on(player, DOROT);
! 595: msg("You feel your skin starting to rot away!");
! 596: }
! 597: }
! 598:
! 599: if (on(*mp, STEALGOLD)) {
! 600: /*
! 601: * steal some gold
! 602: */
! 603: register long lastpurse;
! 604: register struct linked_list *item;
! 605: register struct object *obj;
! 606:
! 607: lastpurse = purse;
! 608: purse -= GOLDCALC + GOLDCALC;
! 609: if (!save(VS_MAGIC, &player, mp->t_stats.s_lvl/10)) {
! 610: if (on(*mp, ISUNIQUE))
! 611: purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
! 612: purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
! 613: }
! 614: if (purse < 0)
! 615: purse = 0;
! 616: if (purse != lastpurse) {
! 617: msg("Your purse feels lighter");
! 618:
! 619: /* Give the gold to the thief */
! 620: for (item=mp->t_pack; item != NULL; item=next(item)) {
! 621: obj = OBJPTR(item);
! 622: if (obj->o_type == GOLD) {
! 623: obj->o_count += lastpurse - purse;
! 624: break;
! 625: }
! 626: }
! 627:
! 628: /* Did we do it? */
! 629: if (item == NULL) { /* Then make some */
! 630: item = new_item(sizeof *obj);
! 631: obj = OBJPTR(item);
! 632: obj->o_type = GOLD;
! 633: obj->o_count = lastpurse - purse;
! 634: obj->o_hplus = obj->o_dplus = 0;
! 635: strcpy(obj->o_damage,"0d0");
! 636: strcpy(obj->o_hurldmg,"0d0");
! 637: obj->o_ac = 11;
! 638: obj->contents = NULL;
! 639: obj->o_group = 0;
! 640: obj->o_flags = 0;
! 641: obj->o_mark[0] = '\0';
! 642: obj->o_pos = mp->t_pos;
! 643:
! 644: attach(mp->t_pack, item);
! 645: }
! 646: }
! 647:
! 648: turn_on(*mp, ISFLEE);
! 649: turn_on(*mp, ISINVIS);
! 650: }
! 651:
! 652: if (on(*mp, STEALMAGIC)) {
! 653: register struct linked_list *list, *steal;
! 654: register struct object *obj;
! 655: register int nobj;
! 656:
! 657: /*
! 658: * steal a magic item, look through the pack
! 659: * and pick out one we like.
! 660: */
! 661: steal = NULL;
! 662: for (nobj = 0, list = pack; list != NULL; list = next(list))
! 663: {
! 664: obj = OBJPTR(list);
! 665: if (!is_current(obj) &&
! 666: is_magic(obj) &&
! 667: rnd(++nobj) == 0)
! 668: steal = list;
! 669: }
! 670: if (steal != NULL)
! 671: {
! 672: register struct object *obj;
! 673: struct linked_list *item;
! 674:
! 675: obj = OBJPTR(steal);
! 676: if (on(*mp, ISUNIQUE))
! 677: monsters[mp->t_index].m_normal = TRUE;
! 678: item = find_mons(mp->t_pos.y, mp->t_pos.x);
! 679: killed(item, FALSE, FALSE);
! 680: if (obj->o_count > 1 && obj->o_group == 0) {
! 681: register int oc;
! 682:
! 683: oc = --(obj->o_count);
! 684: obj->o_count = 1;
! 685: sprintf(outstring,"The %s stole %s!", mname, inv_name(obj, TRUE));
! 686: msg(outstring);
! 687: obj->o_count = oc;
! 688: }
! 689: else {
! 690: sprintf(outstring,"The %s stole %s!", mname, inv_name(obj, TRUE));
! 691: msg(outstring);
! 692: detach(pack, steal);
! 693:
! 694: /* If this is a relic, clear its holding field */
! 695: if (obj->o_type == RELIC)
! 696: cur_relic[obj->o_which] = 0;
! 697:
! 698: o_discard(steal);
! 699: inpack--;
! 700: }
! 701: updpack(FALSE);
! 702: }
! 703: }
! 704: }
! 705: }
! 706: else {
! 707: /* If the thing was trying to surprise, no good */
! 708: if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
! 709:
! 710: else if (thrown) m_bounce(weapon, mp, mname);
! 711: else miss(weapon, mp, mname, NULL);
! 712: }
! 713: if (fight_flush)
! 714: md_flushinp();
! 715: count = 0;
! 716: status(FALSE);
! 717: return(did_hit);
! 718: }
! 719:
! 720: /*
! 721: * swing:
! 722: * returns true if the swing hits
! 723: */
! 724:
! 725: bool
! 726: swing(short class, int at_lvl, int op_arm, int wplus)
! 727: {
! 728: register int res = rnd(20)+1;
! 729: register int need;
! 730:
! 731: need = att_mat[class].base -
! 732: att_mat[class].factor *
! 733: ((min(at_lvl, att_mat[class].max_lvl) -
! 734: att_mat[class].offset)/att_mat[class].range) +
! 735: (10 - op_arm);
! 736: if (need > 20 && need <= 25) need = 20;
! 737:
! 738: return (res+wplus >= need);
! 739: }
! 740:
! 741: /*
! 742: * roll_em:
! 743: * Roll several attacks
! 744: */
! 745:
! 746: bool
! 747: roll_em(struct thing *att_er, struct thing *def_er, struct object *weap,
! 748: bool hurl, struct object *cur_weapon, bool back_stab)
! 749: {
! 750: register struct stats *att, *def;
! 751: register char *cp = NULL;
! 752: register int ndice, nsides, nplus, def_arm;
! 753: bool did_hit = FALSE;
! 754: int prop_hplus, prop_dplus;
! 755: int vampiric_damage;
! 756:
! 757: /* Get statistics */
! 758: att = &att_er->t_stats;
! 759: def = &def_er->t_stats;
! 760:
! 761: prop_hplus = prop_dplus = 0;
! 762: if (weap == NULL)
! 763: cp = att->s_dmg;
! 764: else if (hurl) {
! 765: if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
! 766: cur_weapon->o_which == weap->o_launch)
! 767: {
! 768: cp = weap->o_hurldmg;
! 769: prop_hplus = cur_weapon->o_hplus;
! 770: prop_dplus = cur_weapon->o_dplus;
! 771: }
! 772: else
! 773: cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg);
! 774: }
! 775: else {
! 776: if (weap->o_type == RELIC) {
! 777: switch (weap->o_which) {
! 778: case MUSTY_DAGGER: cp = "1d4+1/1d4+1";
! 779: when YEENOGHU_FLAIL: cp = "3d6/paralyze/confuse";
! 780: when HRUGGEK_MSTAR: cp = "3d10";
! 781: when MING_STAFF: cp = "1d8";
! 782: when ASMO_ROD: cp = "2d8+1";
! 783: when ORCUS_WAND: cp = "destroy";
! 784: }
! 785: }
! 786: else cp = weap->o_damage;
! 787: /*
! 788: * Drain a staff of striking
! 789: */
! 790: if (weap->o_type == STICK && weap->o_which == WS_HIT
! 791: && weap->o_charges == 0)
! 792: {
! 793: strcpy(weap->o_damage,"0d0");
! 794: weap->o_hplus = weap->o_dplus = 0;
! 795: }
! 796: }
! 797: for (;;)
! 798: {
! 799: int damage;
! 800: int hplus = prop_hplus;
! 801: int dplus = prop_dplus;
! 802:
! 803: if (weap != NULL && weap->o_type == RELIC) {
! 804: switch (weap->o_which) {
! 805: case MUSTY_DAGGER:
! 806: if (att != &pstats || /* Not player or good stats */
! 807: (str_compute() > 15 && dex_compute() > 15)) {
! 808:
! 809: hplus += 6;
! 810: dplus += 6;
! 811:
! 812: /* Give an additional strength and dex bonus */
! 813: if (att == &pstats) {
! 814: hplus += str_plus(str_compute()) +
! 815: dext_plus(dex_compute());
! 816: dplus += dext_plus(dex_compute()) +
! 817: add_dam(str_compute());
! 818: }
! 819: else {
! 820: hplus += str_plus(att->s_str) +
! 821: dext_plus(att->s_dext);
! 822: dplus += dext_plus(att->s_dext) +
! 823: add_dam(att->s_str);
! 824: }
! 825: }
! 826: else {
! 827: hplus -= 3;
! 828: dplus -= 3;
! 829: }
! 830: when YEENOGHU_FLAIL:
! 831: case HRUGGEK_MSTAR:
! 832: hplus += 3;
! 833: dplus += 3;
! 834: when MING_STAFF:
! 835: hplus += 2;
! 836: dplus += 2;
! 837: }
! 838: }
! 839: else if (weap != NULL) {
! 840: hplus += weap->o_hplus;
! 841: dplus += weap->o_dplus;
! 842: }
! 843:
! 844: /* Is attacker weak? */
! 845: if (on(*att_er, HASSTINK)) hplus -= 2;
! 846:
! 847: if (att == &pstats) /* Is the attacker the player? */
! 848: {
! 849: hplus += hitweight(); /* adjust for encumberence */
! 850: dplus += hung_dam(); /* adjust damage for hungry player */
! 851: dplus += ring_value(R_ADDDAM);
! 852: }
! 853: if (back_stab || (weap && att != &pstats && on(*att_er, CANBSTAB)))
! 854: hplus += 4; /* add in pluses for backstabbing */
! 855:
! 856: /* Get the damage */
! 857: while (isspace(*cp)) cp++;
! 858: if (!isdigit(*cp)) {
! 859: if (strncmp(cp, "confuse", 7) == 0) ndice = CONF_DAMAGE;
! 860: else if (strncmp(cp, "paralyze", 8) == 0) ndice = PARAL_DAMAGE;
! 861: else if (strncmp(cp, "destroy", 7) == 0) ndice = DEST_DAMAGE;
! 862: else ndice = 0;
! 863: nsides = 0;
! 864: nplus = 0;
! 865: }
! 866: else {
! 867: char *oldcp;
! 868:
! 869: /* Get the number of damage dice */
! 870: ndice = atoi(cp);
! 871: if ((cp = strchr(cp, 'd')) == NULL)
! 872: break;
! 873:
! 874: /* Skip the 'd' and get the number of sides per die */
! 875: nsides = atoi(++cp);
! 876:
! 877: /* Check for an addition -- save old place in case none is found */
! 878: oldcp = cp;
! 879: if ((cp = strchr(cp, '+')) != NULL) nplus = atoi(++cp);
! 880: else {
! 881: nplus = 0;
! 882: cp = oldcp;
! 883: }
! 884: }
! 885:
! 886: if (def == &pstats) { /* Monster attacks player */
! 887: def_arm = ac_compute() - dext_prot(dex_compute());
! 888: hplus += str_plus(att->s_str)+dext_plus(att->s_dext);
! 889: }
! 890: else { /* Player attacks monster */
! 891: def_arm = def->s_arm - dext_prot(def->s_dext);
! 892: hplus += str_plus(str_compute())+dext_plus(dex_compute());
! 893: }
! 894:
! 895: if (swing(att_er->t_ctype, att->s_lvl, def_arm, hplus)) {
! 896: register int proll;
! 897:
! 898: /* Take care of special effects */
! 899: switch (ndice) {
! 900: case CONF_DAMAGE:
! 901: if (def == &pstats) { /* Monster attacks player */
! 902: if (!save(VS_MAGIC, &player, 0) && off(player, ISCLEAR)) {
! 903: msg("You feel disoriented.");
! 904: if (find_slot(unconfuse))
! 905: lengthen(unconfuse, rnd(8)+HUHDURATION);
! 906: else
! 907: fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
! 908: turn_on(player, ISHUH);
! 909: }
! 910: else msg("You feel dizzy, but it quickly passes.");
! 911: }
! 912: /* Player hits monster */
! 913: else if (!save(VS_MAGIC, def_er, 0) && off(*def_er, ISCLEAR)) {
! 914: msg("The artifact warms with pleasure.");
! 915: turn_on(*def_er, ISHUH);
! 916: }
! 917: did_hit = TRUE;
! 918: when PARAL_DAMAGE:
! 919: if (def == &pstats) { /* Monster attacks player */
! 920: if (!save(VS_MAGIC, &player, 0) && off(player, CANINWALL)) {
! 921: msg("You stiffen up.");
! 922: no_command += FREEZETIME;
! 923: }
! 924: }
! 925: else if (!save(VS_MAGIC, def_er, 0)) { /* Player hits monster */
! 926: msg("The artifact hums happily.");
! 927: turn_off(*def_er, ISRUN);
! 928: turn_on(*def_er, ISHELD);
! 929: }
! 930: did_hit = TRUE;
! 931: when DEST_DAMAGE:
! 932: if (def == &pstats) { /* Monster attacks player */
! 933: msg("You feel a tug at your life force.");
! 934: if (!save(VS_MAGIC, &player, -4)) {
! 935: msg("The wand devours your soul.");
! 936: def->s_hpt = 0;
! 937: }
! 938: }
! 939: /* Player hits monster */
! 940: else if (!save(VS_MAGIC, def_er, -4)) {
! 941: msg("The artifact draws energy.");
! 942:
! 943: /* Give the player half the monster's hits */
! 944: att->s_hpt += def->s_hpt/2;
! 945: if (att->s_hpt > att_er->maxstats.s_hpt)
! 946: att->s_hpt = att_er->maxstats.s_hpt;
! 947:
! 948: /* Kill the monster */
! 949: def->s_hpt = 0;
! 950: }
! 951: did_hit = TRUE;
! 952: otherwise:
! 953: /* Heil's ankh always gives maximum damage */
! 954: if (att == &pstats && cur_relic[HEIL_ANKH])
! 955: proll = ndice * nsides;
! 956: else proll = roll(ndice, nsides);
! 957:
! 958: if (ndice + nsides > 0 && proll < 1)
! 959: debug("Damage for %dd%d came out %d.",
! 960: ndice, nsides, proll);
! 961: damage = dplus + proll + nplus;
! 962: if (def == &pstats)
! 963: damage += add_dam(att->s_str);
! 964: else
! 965: damage += add_dam(str_compute());
! 966:
! 967: /* Check for half damage monsters */
! 968: if (on(*def_er, HALFDAMAGE)) damage /= 2;
! 969:
! 970: /* add in multipliers for backstabbing */
! 971: if (back_stab ||
! 972: (weap && att != &pstats && on(*att_er, CANBSTAB))) {
! 973: int mult = 2 + (att->s_lvl-1)/4; /* Normal multiplier */
! 974:
! 975: if (mult > 5 && att != &pstats)
! 976: mult = 5;/*be nice with maximum of 5x for monsters*/
! 977: if (weap->o_type == RELIC && weap->o_which == MUSTY_DAGGER)
! 978: mult++;
! 979: damage *= mult;
! 980: }
! 981:
! 982: /* Check for no-damage and division */
! 983: if (on(*def_er, BLOWDIVIDE)) {
! 984: damage = 0;
! 985: creat_mons(def_er, def_er->t_index, FALSE);
! 986: light(&hero);
! 987: }
! 988: /* check for immunity to metal -- RELICS are always bad */
! 989: if (on(*def_er, NOMETAL) && weap != NULL &&
! 990: weap->o_type != RELIC && weap->o_flags & ISMETAL) {
! 991: damage = 0;
! 992: }
! 993:
! 994: /*
! 995: * If defender is wearing a cloak of displacement -- no damage
! 996: * the first time. (unless its a hurled magic missile)
! 997: */
! 998: if ( ((weap == NULL) || weap->o_type != MISSILE) &&
! 999: def == &pstats &&
! 1000: cur_misc[WEAR_CLOAK] != NULL &&
! 1001: cur_misc[WEAR_CLOAK]->o_which == MM_DISP &&
! 1002: off(*att_er, MISSEDDISP)) {
! 1003: damage = 0;
! 1004: did_hit = FALSE;
! 1005: turn_on(*att_er, MISSEDDISP);
! 1006: if (cansee(att_er->t_pos.y, att_er->t_pos.x) &&
! 1007: !invisible(att_er))
! 1008: msg("The %s looks amazed",
! 1009: monsters[att_er->t_index].m_name);
! 1010: }
! 1011: else {
! 1012: def->s_hpt -= max(0, damage); /* Do the damage */
! 1013: did_hit = TRUE;
! 1014: }
! 1015:
! 1016: vampiric_damage = damage;
! 1017: if (def->s_hpt < 0) /* only want REAL damage inflicted */
! 1018: vampiric_damage += def->s_hpt;
! 1019: if (vampiric_damage < 0)
! 1020: vampiric_damage = 0;
! 1021: if (att == &pstats && ISWEARING(R_VAMPREGEN) && !hurl) {
! 1022: if ((pstats.s_hpt += vampiric_damage/2) > max_stats.s_hpt)
! 1023: pstats.s_hpt = max_stats.s_hpt;
! 1024: }
! 1025: debug ("hplus=%d dmg=%d", hplus, damage);
! 1026: }
! 1027: }
! 1028: if ((cp = strchr(cp, '/')) == NULL)
! 1029: break;
! 1030: cp++;
! 1031: }
! 1032: return did_hit;
! 1033: }
! 1034:
! 1035: /*
! 1036: * prname:
! 1037: * The print name of a combatant
! 1038: */
! 1039:
! 1040: char *
! 1041: prname(const char *who, bool upper)
! 1042: {
! 1043: static char tbuf[LINELEN];
! 1044:
! 1045: *tbuf = '\0';
! 1046: if (who == 0)
! 1047: strcpy(tbuf, "you");
! 1048: else if (on(player, ISBLIND))
! 1049: strcpy(tbuf, "it");
! 1050: else
! 1051: {
! 1052: strcpy(tbuf, "the ");
! 1053: strcat(tbuf, who);
! 1054: }
! 1055: if (upper)
! 1056: *tbuf = toupper(*tbuf);
! 1057: return tbuf;
! 1058: }
! 1059:
! 1060: /*
! 1061: * hit:
! 1062: * Print a message to indicate a succesful hit
! 1063: */
! 1064:
! 1065: void
! 1066: hit(struct object *weapon, struct thing *tp, const char *er, const char *ee,
! 1067: bool back_stab)
! 1068: {
! 1069: register char *s = NULL;
! 1070: char
! 1071: att_name[80], /* Name of attacker */
! 1072: def_name[80];/* Name of defender */
! 1073: bool see_monst = !invisible(tp); /* Can the player see the monster? */
! 1074:
! 1075: /* What do we call the attacker? */
! 1076: if (er == NULL) { /* Player is attacking */
! 1077: strcpy(att_name, prname(er, TRUE));
! 1078: strcpy(def_name, see_monst ? prname(ee, FALSE) : "something");
! 1079: }
! 1080: else {
! 1081: strcpy(att_name, see_monst ? prname(er, TRUE) : "Something");
! 1082:
! 1083: /* If the monster is using a weapon and we can see it, report it */
! 1084: if (weapon != NULL && see_monst) {
! 1085: strcat(att_name, "'s ");
! 1086: strcat(att_name, weap_name(weapon));
! 1087: }
! 1088:
! 1089: strcpy(def_name, prname(ee, FALSE));
! 1090: }
! 1091:
! 1092: addmsg(att_name);
! 1093: if (terse) {
! 1094: if (back_stab)
! 1095: s = " backstab!";
! 1096: else
! 1097: s = " hit.";
! 1098: }
! 1099: else {
! 1100: if (back_stab)
! 1101: s = (er == 0 ? " have backstabbed " : " has backstabbed ");
! 1102: else {
! 1103: switch (rnd(4))
! 1104: {
! 1105: case 0: s = " scored an excellent hit on ";
! 1106: when 1: s = " hit ";
! 1107: when 2: s = (er == 0 ? " have injured " : " has injured ");
! 1108: when 3: s = (er == 0 ? " swing and hit " : " swings and hits ");
! 1109: }
! 1110: }
! 1111: }
! 1112: addmsg(s);
! 1113: if (!terse)
! 1114: addmsg(def_name);
! 1115: endmsg();
! 1116: }
! 1117:
! 1118: /*
! 1119: * miss:
! 1120: * Print a message to indicate a poor swing
! 1121: */
! 1122:
! 1123: void
! 1124: miss(struct object *weapon, struct thing *tp, const char *er, const char *ee)
! 1125: {
! 1126: register char *s = NULL;
! 1127: char
! 1128: att_name[80], /* Name of attacker */
! 1129: def_name[80];/* Name of defender */
! 1130: bool see_monst = !invisible(tp); /* Can the player see the monster? */
! 1131:
! 1132: /* What do we call the attacker? */
! 1133: if (er == NULL) { /* Player is attacking */
! 1134: strcpy(att_name, prname(er, TRUE));
! 1135: strcpy(def_name, see_monst ? prname(ee, FALSE) : "something");
! 1136: }
! 1137: else {
! 1138: strcpy(att_name, see_monst ? prname(er, TRUE) : "Something");
! 1139:
! 1140: /* If the monster is using a weapon and we can see it, report it */
! 1141: if (weapon != NULL && see_monst) {
! 1142: strcat(att_name, "'s ");
! 1143: strcat(att_name, weap_name(weapon));
! 1144: }
! 1145:
! 1146: strcpy(def_name, prname(ee, FALSE));
! 1147: }
! 1148:
! 1149: addmsg(att_name);
! 1150: switch (terse ? 0 : rnd(4))
! 1151: {
! 1152: case 0: s = (er == 0 ? " miss" : " misses");
! 1153: when 1: s = (er == 0 ? " swing and miss" : " swings and misses");
! 1154: when 2: s = (er == 0 ? " barely miss" : " barely misses");
! 1155: when 3: s = (er == 0 ? " don't hit" : " doesn't hit");
! 1156: }
! 1157: addmsg(s);
! 1158: if (!terse)
! 1159: addmsg(" %s", def_name);
! 1160: endmsg();
! 1161: }
! 1162:
! 1163: /*
! 1164: * dext_plus:
! 1165: * compute to-hit bonus for dexterity
! 1166: */
! 1167:
! 1168: int
! 1169: dext_plus(int dexterity)
! 1170: {
! 1171: return (dexterity > 10 ? (dexterity-13)/3 : (dexterity-10)/3);
! 1172: }
! 1173:
! 1174:
! 1175: /*
! 1176: * dext_prot:
! 1177: * compute armor class bonus for dexterity
! 1178: */
! 1179:
! 1180: int
! 1181: dext_prot(int dexterity)
! 1182: {
! 1183: return ((dexterity-10)/2);
! 1184: }
! 1185: /*
! 1186: * str_plus:
! 1187: * compute bonus/penalties for strength on the "to hit" roll
! 1188: */
! 1189:
! 1190: int
! 1191: str_plus(short str)
! 1192: {
! 1193: return((str-10)/3);
! 1194: }
! 1195:
! 1196: /*
! 1197: * add_dam:
! 1198: * compute additional damage done for exceptionally high or low strength
! 1199: */
! 1200:
! 1201: int
! 1202: add_dam(short str)
! 1203: {
! 1204: return((str-9)/2);
! 1205: }
! 1206:
! 1207: /*
! 1208: * hung_dam:
! 1209: * Calculate damage depending on players hungry state
! 1210: */
! 1211: int
! 1212: hung_dam(void)
! 1213: {
! 1214: reg int howmuch = 0;
! 1215:
! 1216: switch(hungry_state) {
! 1217: case F_OKAY:
! 1218: case F_HUNGRY: howmuch = 0;
! 1219: when F_WEAK: howmuch = -1;
! 1220: when F_FAINT: howmuch = -2;
! 1221: }
! 1222: return howmuch;
! 1223: }
! 1224:
! 1225: /*
! 1226: * thunk:
! 1227: * A missile hits a monster
! 1228: */
! 1229:
! 1230: void
! 1231: thunk(struct object *weap, struct thing *tp, const char *mname)
! 1232: {
! 1233: /* tp: Defender */
! 1234: char *def_name; /* Name of defender */
! 1235:
! 1236: /* What do we call the defender? */
! 1237: if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
! 1238: def_name = "something";
! 1239: else def_name = prname(mname, FALSE);
! 1240:
! 1241: if (weap->o_type == WEAPON){
! 1242: sprintf(outstring,"The %s hits %s", weaps[weap->o_which].w_name, def_name);
! 1243: msg(outstring);
! 1244: }
! 1245: else if (weap->o_type == MISSILE){
! 1246: sprintf(outstring,"The %s hits %s",ws_magic[weap->o_which].mi_name, def_name);
! 1247: msg(outstring);
! 1248: }
! 1249: else
! 1250: msg("You hit %s.", def_name);
! 1251: }
! 1252:
! 1253: /*
! 1254: * mthunk:
! 1255: * A missile from a monster hits the player
! 1256: */
! 1257:
! 1258: void
! 1259: m_thunk(struct object *weap, struct thing *tp, const char *mname)
! 1260: {
! 1261: char *att_name; /* Name of attacker */
! 1262:
! 1263: /* What do we call the attacker? */
! 1264: if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
! 1265: att_name = "Something";
! 1266: else att_name = prname(mname, TRUE);
! 1267:
! 1268: if (weap->o_type == WEAPON){
! 1269: sprintf(outstring,"%s's %s hits you.", att_name, weaps[weap->o_which].w_name);
! 1270: msg(outstring);
! 1271: }
! 1272: else if (weap->o_type == MISSILE){
! 1273: sprintf(outstring,"%s's %s hits you.", att_name, ws_magic[weap->o_which].mi_name);
! 1274: msg(outstring);
! 1275: }
! 1276: else
! 1277: msg("%s hits you.", att_name);
! 1278: }
! 1279:
! 1280: /*
! 1281: * bounce:
! 1282: * A missile misses a monster
! 1283: */
! 1284:
! 1285: void
! 1286: bounce(struct object *weap, struct thing *tp, const char *mname)
! 1287: {
! 1288: /* tp: Defender */
! 1289: char *def_name; /* Name of defender */
! 1290:
! 1291: /* What do we call the defender? */
! 1292: if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
! 1293: def_name = "something";
! 1294: else def_name = prname(mname, FALSE);
! 1295:
! 1296: if (weap->o_type == WEAPON){
! 1297: sprintf(outstring,"The %s misses %s",weaps[weap->o_which].w_name, def_name);
! 1298: msg(outstring);
! 1299: }
! 1300: else if (weap->o_type == MISSILE){
! 1301: sprintf(outstring,"The %s misses %s",ws_magic[weap->o_which].mi_name, def_name);
! 1302: msg(outstring);
! 1303: }
! 1304: else
! 1305: msg("You missed %s.", def_name);
! 1306: }
! 1307:
! 1308: /*
! 1309: * m_bounce:
! 1310: A missle from a monster misses the player
! 1311: */
! 1312:
! 1313: void
! 1314: m_bounce(struct object *weap, struct thing *tp, const char *mname)
! 1315: {
! 1316: char *att_name; /* Name of attacker */
! 1317:
! 1318: /* What do we call the attacker? */
! 1319: if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
! 1320: att_name = "Something";
! 1321: else att_name = prname(mname, TRUE);
! 1322:
! 1323: if (weap->o_type == WEAPON){
! 1324: sprintf(outstring,"%s's %s misses you.", att_name, weaps[weap->o_which].w_name);
! 1325: msg(outstring);
! 1326: }
! 1327: else if (weap->o_type == MISSILE){
! 1328: sprintf(outstring,"%s's %s misses you.", att_name, ws_magic[weap->o_which].mi_name);
! 1329: msg(outstring);
! 1330: }
! 1331: else
! 1332: msg("%s misses you.", att_name);
! 1333: }
! 1334:
! 1335:
! 1336: /*
! 1337: * is_magic:
! 1338: * Returns true if an object radiates magic
! 1339: */
! 1340:
! 1341: bool
! 1342: is_magic(struct object *obj)
! 1343: {
! 1344: switch (obj->o_type)
! 1345: {
! 1346: case ARMOR:
! 1347: return obj->o_ac != armors[obj->o_which].a_class;
! 1348: when WEAPON:
! 1349: return obj->o_hplus != 0 || obj->o_dplus != 0;
! 1350: when POTION:
! 1351: case SCROLL:
! 1352: case STICK:
! 1353: case RING:
! 1354: case MM:
! 1355: case RELIC:
! 1356: return TRUE;
! 1357: }
! 1358: return FALSE;
! 1359: }
! 1360:
! 1361: /*
! 1362: * killed:
! 1363: * Called to put a monster to death
! 1364: */
! 1365:
! 1366: void
! 1367: killed(struct linked_list *item, bool pr, bool points)
! 1368: {
! 1369: register struct thing *tp;
! 1370: register struct linked_list *pitem, *nexti;
! 1371: const char *monst;
! 1372:
! 1373: tp = THINGPTR(item);
! 1374:
! 1375: if (pr)
! 1376: {
! 1377: addmsg(terse ? "Defeated " : "You have defeated ");
! 1378: if (on(player, ISBLIND))
! 1379: msg("it.");
! 1380: else
! 1381: {
! 1382: if (cansee(tp->t_pos.y, tp->t_pos.x) && !invisible(tp))
! 1383: monst = monsters[tp->t_index].m_name;
! 1384: else {
! 1385: if (terse) monst = "something";
! 1386: else monst = "thing";
! 1387: }
! 1388: if (!terse)
! 1389: addmsg("the ");
! 1390: msg("%s.", monst);
! 1391: }
! 1392: }
! 1393:
! 1394: /* Take care of any residual effects of the monster */
! 1395: check_residue(tp);
! 1396:
! 1397: if (points) {
! 1398: unsigned long test; /* For overflow check */
! 1399:
! 1400: test = pstats.s_exp + tp->t_stats.s_exp;
! 1401:
! 1402: /* Do an overflow check before increasing experience */
! 1403: if (test > pstats.s_exp) pstats.s_exp = test;
! 1404:
! 1405: /*
! 1406: * Do adjustments if he went up a level
! 1407: */
! 1408: check_level(TRUE);
! 1409: }
! 1410:
! 1411: /*
! 1412: * Empty the monsters pack
! 1413: */
! 1414: pitem = tp->t_pack;
! 1415:
! 1416: /*
! 1417: * Get rid of the monster.
! 1418: */
! 1419: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' ');
! 1420: mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
! 1421: detach(mlist, item);
! 1422: /*
! 1423: * empty his pack
! 1424: */
! 1425: while (pitem != NULL)
! 1426: {
! 1427: nexti = next(tp->t_pack);
! 1428: (OBJPTR(pitem))->o_pos = tp->t_pos;
! 1429: detach(tp->t_pack, pitem);
! 1430: if (points)
! 1431: fall(pitem, FALSE);
! 1432: else
! 1433: o_discard(pitem);
! 1434: pitem = nexti;
! 1435: }
! 1436: turn_on(*tp, ISDEAD);
! 1437: attach(monst_dead, item);
! 1438: }
! 1439:
! 1440:
! 1441: /*
! 1442: * Returns a pointer to the weapon the monster is wielding corresponding to
! 1443: * the given thrown weapon. If no thrown item is given, try to find any
! 1444: * decent weapon.
! 1445: */
! 1446:
! 1447: struct object *
! 1448: wield_weap(struct object *thrown, struct thing *mp)
! 1449: {
! 1450: int look_for = 0, /* The projectile weapon we are looking for */
! 1451: new_rate, /* The rating of a prospective weapon */
! 1452: cand_rate = -1; /* Rating of current candidate -- higher is better */
! 1453: register struct linked_list *pitem;
! 1454: register struct object *obj, *candidate = NULL;
! 1455:
! 1456: if (thrown != NULL) { /* Using a projectile weapon */
! 1457: switch (thrown->o_which) {
! 1458: case BOLT: look_for = CROSSBOW; /* Find the crossbow */
! 1459: when ARROW: look_for = BOW; /* Find the bow */
! 1460: when ROCK: look_for = SLING; /* find the sling */
! 1461: otherwise: return(NULL);
! 1462: }
! 1463: }
! 1464: else if (off(*mp, ISUNIQUE) && off(*mp, CARRYWEAPON)) return(NULL);
! 1465:
! 1466: for (pitem=mp->t_pack; pitem; pitem=next(pitem)) {
! 1467: obj = OBJPTR(pitem);
! 1468:
! 1469: /*
! 1470: * If we have a thrown weapon, just return the first match
! 1471: * we come to.
! 1472: */
! 1473: if (thrown != NULL && obj->o_type == WEAPON && obj->o_which == look_for)
! 1474: return(obj);
! 1475:
! 1476: /* If we have a usable RELIC, return it */
! 1477: if (thrown == NULL && obj->o_type == RELIC) {
! 1478: switch (obj->o_which) {
! 1479: case MUSTY_DAGGER:
! 1480: case YEENOGHU_FLAIL:
! 1481: case HRUGGEK_MSTAR:
! 1482: case MING_STAFF:
! 1483: case ASMO_ROD:
! 1484: case ORCUS_WAND:
! 1485: return(obj);
! 1486: }
! 1487: }
! 1488:
! 1489: /* Otherwise if it's a usable weapon, it is a good candidate */
! 1490: else if (thrown == NULL && obj->o_type == WEAPON) {
! 1491: switch (obj->o_which) {
! 1492: case DAGGER:
! 1493: new_rate = 0;
! 1494: when BATTLEAXE:
! 1495: new_rate = 1;
! 1496: when MACE:
! 1497: new_rate = 2;
! 1498: when SWORD:
! 1499: new_rate = 3;
! 1500: when PIKE:
! 1501: new_rate = 4;
! 1502: when HALBERD:
! 1503: case SPETUM:
! 1504: new_rate = 6;
! 1505: when BARDICHE:
! 1506: new_rate = 7;
! 1507: when TRIDENT:
! 1508: new_rate = 8;
! 1509: when BASWORD:
! 1510: new_rate = 9;
! 1511: when TWOSWORD:
! 1512: new_rate = 10;
! 1513: otherwise:
! 1514: new_rate = -1;
! 1515: }
! 1516:
! 1517: /* Only switch if this is better than the current candidate */
! 1518: if (new_rate > cand_rate) {
! 1519: cand_rate = new_rate;
! 1520: candidate = obj;
! 1521: }
! 1522: }
! 1523: }
! 1524:
! 1525: return(candidate);
! 1526: }
! 1527:
! 1528: void
! 1529: explode(struct thing *tp)
! 1530: {
! 1531:
! 1532: register int x,y, damage;
! 1533: struct linked_list *item;
! 1534: struct thing *th;
! 1535:
! 1536: msg("the %s explodes!", monsters[tp->t_index].m_name);
! 1537: /*
! 1538: * check to see if it got the hero
! 1539: */
! 1540: if (DISTANCE(hero.x, hero.y, tp->t_pos.x, tp->t_pos.y) <= 25) {
! 1541: msg("the explosion hits you");
! 1542: damage = roll(6,6);
! 1543: if (save(VS_WAND, &player, 0))
! 1544: damage /= 2;
! 1545: if ((pstats.s_hpt -= damage) <= 0)
! 1546: death(tp->t_index);
! 1547: }
! 1548:
! 1549: /*
! 1550: * now check for monsters in vicinity
! 1551: */
! 1552: for (x = tp->t_pos.x-5; x<=tp->t_pos.x+5; x++) {
! 1553: if (x < 0 || x > COLS - 1)
! 1554: continue;
! 1555: for (y = tp->t_pos.y-5; y<=tp->t_pos.y+5; y++) {
! 1556: if (y < 1 || y > LINES - 3)
! 1557: continue;
! 1558: if (isalpha(mvwinch(mw, y, x))) {
! 1559: if ((item = find_mons(y, x)) != NULL) {
! 1560: th = THINGPTR(item);
! 1561: if (th == tp) /* don't count gas spore */
! 1562: continue;
! 1563: damage = roll(6, 6);
! 1564: if (save(VS_WAND, th, 0))
! 1565: damage /= 2;
! 1566: if ((tp->t_stats.s_hpt -= damage) <= 0) {
! 1567: msg("the explosion kills the %s",
! 1568: monsters[th->t_index].m_name);
! 1569: killed(item, FALSE, FALSE);
! 1570: }
! 1571: }
! 1572: }
! 1573: }
! 1574: }
! 1575: }
CVSweb