Annotation of early-roguelike/arogue7/actions.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * actions.c - functions for dealing with monster actions
! 3: *
! 4: * Advanced Rogue
! 5: * Copyright (C) 1984, 1985, 1986 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 <ctype.h>
! 16: #include <limits.h>
! 17: #include "curses.h"
! 18: #include "rogue.h"
! 19: #define MAXINT INT_MAX
! 20: #define MININT INT_MIN
! 21:
! 22: void m_breathe(struct thing *tp);
! 23: void m_select(struct thing *th, bool flee);
! 24: void m_sonic(struct thing *tp);
! 25: void m_spell(struct thing *tp);
! 26: void m_summon(struct thing *tp);
! 27: bool m_use_it(struct thing *tp, bool flee, struct room *rer, struct room *ree);
! 28: bool m_use_pack(struct thing *monster, coord *monst_pos, coord *defend_pos,
! 29: int dist, coord *shoot_dir);
! 30:
! 31: /*
! 32: * Did we disrupt a spell?
! 33: */
! 34: void
! 35: dsrpt_monster(struct thing *tp, bool always, bool see_him)
! 36: {
! 37: switch (tp->t_action) {
! 38: case A_SUMMON:
! 39: case A_MISSILE:
! 40: case A_SLOW:
! 41: tp->t_action = A_NIL; /* Just make the old fellow start over again */
! 42: tp->t_no_move = movement(tp);
! 43: tp->t_using = NULL;/* Just to be on the safe side */
! 44: turn_on(*tp, WASDISRUPTED);
! 45: if (see_him)
! 46: msg("%s's spell has been disrupted.",prname(monster_name(tp),TRUE));
! 47: /*
! 48: * maybe choose something else to do next time since player
! 49: * is disrupting us
! 50: */
! 51: tp->t_summon *= 2;
! 52: tp->t_cast /= 2;
! 53: return;
! 54: }
! 55:
! 56: /* We may want to disrupt other actions, too */
! 57: if (always) {
! 58: tp->t_action = A_NIL; /* Just make the old fellow start over again */
! 59: tp->t_no_move = movement(tp);
! 60: tp->t_using = NULL;/* Just to be on the safe side */
! 61: }
! 62: }
! 63:
! 64: void
! 65: dsrpt_player(void)
! 66: {
! 67: int which, action;
! 68: struct linked_list *item;
! 69: struct object *obj;
! 70:
! 71: action = player.t_action;
! 72: which = player.t_selection;
! 73:
! 74: switch (action) {
! 75: case C_CAST: /* Did we disrupt a spell? */
! 76: case C_PRAY:
! 77: case C_CHANT:
! 78: {
! 79: msg("Your %s was disrupted!", action == C_CAST ? "spell" : "prayer");
! 80:
! 81: /* Charge him anyway */
! 82: if (action == C_CAST)
! 83: spell_power += magic_spells[which].s_cost;
! 84: else if (action == C_PRAY)
! 85: pray_time += cleric_spells[which].s_cost;
! 86: else if (action == C_CHANT)
! 87: chant_time += druid_spells[which].s_cost;
! 88: }
! 89: when C_COUNT: /* counting of gold? */
! 90: {
! 91: if (purse > 0) {
! 92: msg("Your gold goes flying everywhere!");
! 93: do {
! 94: item = spec_item(GOLD, 0, 0, 0);
! 95: obj = OBJPTR(item);
! 96: obj->o_count = min(purse, rnd(10)+1);
! 97: purse -= obj->o_count;
! 98: obj->o_pos = hero;
! 99: fall(item, FALSE);
! 100: } while (purse > 0 && rnd(10) != 1);
! 101: }
! 102: }
! 103: when C_EAT:
! 104: msg("You gag on your food for a moment.");
! 105: del_pack(player.t_using);
! 106:
! 107: when A_PICKUP:
! 108: msg("You drop what you are picking up!");
! 109:
! 110: when C_SEARCH: /* searching for traps and secret doors... */
! 111: msg("Oww....You decide to stop searching.");
! 112: count = 0; /* don't search again */
! 113:
! 114: when C_SETTRAP:
! 115: msg("Oww....You can't get a trap set.");
! 116:
! 117: when A_NIL:
! 118: default:
! 119: return;
! 120: }
! 121: player.t_no_move = movement(&player); /* disoriented for a while */
! 122: player.t_action = A_NIL;
! 123: player.t_selection = 0;
! 124: player.t_using = NULL;
! 125: }
! 126:
! 127: /*
! 128: * m_act:
! 129: * If the critter isn't doing anything, choose an action for it.
! 130: * Otherwise, let it perform its chosen action.
! 131: */
! 132:
! 133: void
! 134: m_act(struct thing *tp)
! 135: {
! 136: struct object *obj;
! 137: bool flee; /* Are we scared? */
! 138:
! 139: /* What are we planning to do? */
! 140: switch (tp->t_action) {
! 141: default:
! 142: /* An unknown action! */
! 143: msg("Unknown monster action (%d)", tp->t_action);
! 144:
! 145: /* Fall through */
! 146:
! 147: case A_NIL:
! 148: /* If the monster is fairly intelligent and about to die, it
! 149: * may turn tail and run. But if we are a FRIENDLY creature
! 150: * in the hero's service, don't run.
! 151: */
! 152: if (off(*tp, ISFLEE) &&
! 153: tp->t_stats.s_hpt < tp->maxstats.s_hpt &&
! 154: tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/6) &&
! 155: (off(*tp, ISFRIENDLY) || tp->t_dest != &hero) &&
! 156: rnd(25) < tp->t_stats.s_intel) {
! 157: turn_on(*tp, ISFLEE);
! 158:
! 159: /* It is okay to turn tail */
! 160: tp->t_oldpos = tp->t_pos;
! 161: }
! 162:
! 163: /* Should the monster run away? */
! 164: flee = on(*tp, ISFLEE) ||
! 165: ((tp->t_dest == &hero) && on(player, ISINWALL) &&
! 166: off(*tp, CANINWALL));
! 167:
! 168: m_select(tp, flee); /* Select an action */
! 169: return;
! 170:
! 171: when A_ATTACK:
! 172: /*
! 173: * We're trying to attack the player or monster at t_newpos
! 174: * if the prey moved, do nothing
! 175: */
! 176: obj = tp->t_using ? OBJPTR(tp->t_using) : NULL;
! 177: if (ce(tp->t_newpos, hero)) {
! 178: attack(tp, obj, FALSE);
! 179: }
! 180: else if (mvwinch(mw, tp->t_newpos.y, tp->t_newpos.x) &&
! 181: step_ok(tp->t_newpos.y, tp->t_newpos.x, FIGHTOK, tp)) {
! 182: skirmish(tp, &tp->t_newpos, obj, FALSE);
! 183: }
! 184:
! 185: when A_SELL:
! 186: /* Is the player still next to us? */
! 187: if (ce(tp->t_newpos, hero)) sell(tp);
! 188:
! 189: /* The darned player moved away */
! 190: else if (off(player, ISBLIND) &&
! 191: cansee(unc(tp->t_pos)) &&
! 192: (off(*tp, ISINVIS) || on(player, CANSEE)) &&
! 193: (off(*tp, ISSHADOW) || on(player, CANSEE)) &&
! 194: (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT)))
! 195: msg("%s grunts with frustration",prname(monster_name(tp),TRUE));
! 196:
! 197: when A_MOVE:
! 198: /* Let's try to move */
! 199: do_chase(tp);
! 200:
! 201: /* If t_no_move > 0, we found that we have to fight! */
! 202: if (tp->t_no_move > 0) return;
! 203:
! 204: when A_BREATHE:
! 205: /* Breathe on the critter */
! 206: m_breathe(tp);
! 207:
! 208: when A_SLOW:
! 209: /* make him move slower */
! 210: add_slow();
! 211: turn_off(*tp, CANSLOW);
! 212:
! 213: when A_MISSILE:
! 214: /* Start up a magic missile spell */
! 215: m_spell(tp);
! 216:
! 217: when A_SONIC:
! 218: /* Let out a sonic blast! */
! 219: m_sonic(tp);
! 220:
! 221: when A_THROW:
! 222: /* We're throwing something (like an arrow) */
! 223: missile(tp->t_newpos.y, tp->t_newpos.x, tp->t_using, tp);
! 224:
! 225: when A_SUMMON:
! 226: /* We're summoning help */
! 227: m_summon(tp);
! 228:
! 229: when A_USERELIC:
! 230: /* Use our relic */
! 231: m_use_relic(tp);
! 232:
! 233: when A_USEWAND:
! 234: /* use the wand we have */
! 235: m_use_wand(tp);
! 236: }
! 237:
! 238: /* No action now */
! 239: tp->t_action = A_NIL;
! 240: tp->t_using = NULL;
! 241: }
! 242:
! 243: /*
! 244: * m_breathe:
! 245: * Breathe in the chosen direction.
! 246: */
! 247:
! 248: void
! 249: m_breathe(struct thing *tp)
! 250: {
! 251: register int damage;
! 252: register char *breath = "";
! 253:
! 254: damage = tp->t_stats.s_hpt;
! 255: turn_off(*tp, CANSURPRISE);
! 256:
! 257: /* Will it breathe at random */
! 258: if (on(*tp, CANBRANDOM)) {
! 259: /* Turn off random breath */
! 260: turn_off(*tp, CANBRANDOM);
! 261:
! 262: /* Select type of breath */
! 263: switch (rnd(10)) {
! 264: case 0: breath = "acid";
! 265: turn_on(*tp, NOACID);
! 266: when 1: breath = "flame";
! 267: turn_on(*tp, NOFIRE);
! 268: when 2: breath = "lightning bolt";
! 269: turn_on(*tp, NOBOLT);
! 270: when 3: breath = "chlorine gas";
! 271: turn_on(*tp, NOGAS);
! 272: when 4: breath = "ice";
! 273: turn_on(*tp, NOCOLD);
! 274: when 5: breath = "nerve gas";
! 275: turn_on(*tp, NOPARALYZE);
! 276: when 6: breath = "sleeping gas";
! 277: turn_on(*tp, NOSLEEP);
! 278: when 7: breath = "slow gas";
! 279: turn_on(*tp, NOSLOW);
! 280: when 8: breath = "confusion gas";
! 281: turn_on(*tp, ISCLEAR);
! 282: when 9: breath = "fear gas";
! 283: turn_on(*tp, NOFEAR);
! 284: }
! 285: }
! 286:
! 287: /* Or can it breathe acid? */
! 288: else if (on(*tp, CANBACID)) {
! 289: turn_off(*tp, CANBACID);
! 290: breath = "acid";
! 291: }
! 292:
! 293: /* Or can it breathe fire */
! 294: else if (on(*tp, CANBFIRE)) {
! 295: turn_off(*tp, CANBFIRE);
! 296: breath = "flame";
! 297: }
! 298:
! 299: /* Or can it breathe electricity? */
! 300: else if (on(*tp, CANBBOLT)) {
! 301: turn_off(*tp, CANBBOLT);
! 302: breath = "lightning bolt";
! 303: }
! 304:
! 305: /* Or can it breathe gas? */
! 306: else if (on(*tp, CANBGAS)) {
! 307: turn_off(*tp, CANBGAS);
! 308: breath = "chlorine gas";
! 309: }
! 310:
! 311: /* Or can it breathe ice? */
! 312: else if (on(*tp, CANBICE)) {
! 313: turn_off(*tp, CANBICE);
! 314: breath = "ice";
! 315: }
! 316:
! 317: else if (on(*tp, CANBPGAS)) {
! 318: turn_off(*tp, CANBPGAS);
! 319: breath = "nerve gas";
! 320: }
! 321:
! 322: /* can it breathe sleeping gas */
! 323: else if (on(*tp, CANBSGAS)) {
! 324: turn_off(*tp, CANBSGAS);
! 325: breath = "sleeping gas";
! 326: }
! 327:
! 328: /* can it breathe slow gas */
! 329: else if (on(*tp, CANBSLGAS)) {
! 330: turn_off(*tp, CANBSLGAS);
! 331: breath = "slow gas";
! 332: }
! 333:
! 334: /* can it breathe confusion gas */
! 335: else if (on(*tp, CANBCGAS)) {
! 336: turn_off(*tp, CANBCGAS);
! 337: breath = "confusion gas";
! 338: }
! 339:
! 340: /* can it breathe fear gas */
! 341: else {
! 342: turn_off(*tp, CANBFGAS);
! 343: breath = "fear gas";
! 344: }
! 345:
! 346: /* Now breathe -- sets "monst_dead" if it kills someone */
! 347: shoot_bolt(tp, tp->t_pos, tp->t_newpos, FALSE,
! 348: tp->t_index, breath, damage);
! 349:
! 350: running = FALSE;
! 351: if (fight_flush) md_flushinp();
! 352: }
! 353:
! 354: /*
! 355: * m_select:
! 356: * Select an action for the monster.
! 357: * flee: True if running away or player is inaccessible in wall
! 358: */
! 359:
! 360: void
! 361: m_select(struct thing *th, bool flee)
! 362: {
! 363: register struct room *rer, *ree; /* room of chaser, room of chasee */
! 364: int dist = MININT;
! 365: int mindist = MAXINT, maxdist = MININT;
! 366: bool rundoor; /* TRUE means run to a door */
! 367: char sch;
! 368: coord *last_door=0, /* Door we just came from */
! 369: this; /* Temporary destination for chaser */
! 370:
! 371: rer = roomin(&th->t_pos); /* Find room of chaser */
! 372: ree = roomin(th->t_dest); /* Find room of chasee */
! 373:
! 374: /* First see if we want to use an ability or weapon */
! 375: if (m_use_it(th, flee, rer, ree)) return;
! 376:
! 377: /*
! 378: * We don't count monsters on doors as inside rooms here because when
! 379: * a monster is in a room and the player is not in that room, the
! 380: * monster looks for the best door out. If we counted doors as part
! 381: * of the room, the monster would already be on the best door out;
! 382: * so he would never move.
! 383: */
! 384: if ((sch = CCHAR( mvwinch(stdscr, th->t_pos.y, th->t_pos.x) )) == DOOR ||
! 385: sch == SECRETDOOR || sch == PASSAGE) {
! 386: rer = NULL;
! 387: }
! 388: this = *th->t_dest;
! 389:
! 390: /*
! 391: * If we are in a room heading for the player and the player is not
! 392: * in the room with us, we run to the "best" door.
! 393: * If we are in a room fleeing from the player, then we run to the
! 394: * "best" door if he IS in the same room.
! 395: *
! 396: * Note: We don't bother with doors in mazes or if we can walk
! 397: * through walls.
! 398: */
! 399: if (rer != NULL && levtype != MAZELEV && off(*th, CANINWALL)) {
! 400: if (flee) rundoor = (rer == ree);
! 401: else rundoor = (rer != ree);
! 402: }
! 403: else rundoor = FALSE;
! 404:
! 405: if (rundoor) {
! 406: register struct linked_list *exitptr; /* For looping through exits */
! 407: coord *exit, /* A particular door */
! 408: *entrance; /* Place just inside doorway */
! 409: int exity, exitx; /* Door's coordinates */
! 410: char dch='\0'; /* Door character */
! 411:
! 412: if (th->t_doorgoal)
! 413: dch = CCHAR( mvwinch(stdscr, th->t_doorgoal->y, th->t_doorgoal->x) );
! 414:
! 415: /* Do we have a valid goal? */
! 416: if ((dch == PASSAGE || dch == DOOR) && /* A real door */
! 417: (!flee || !ce(*th->t_doorgoal, *th->t_dest))) { /* Prey should not
! 418: * be at door if
! 419: * we are running
! 420: * away
! 421: */
! 422: /* Make sure the player is not in the doorway, either */
! 423: entrance = doorway(rer, th->t_doorgoal);
! 424: if (!flee || entrance == NULL || !ce(*entrance, *th->t_dest)) {
! 425: this = *th->t_doorgoal;
! 426: dist = 0; /* Indicate that we have our door */
! 427: }
! 428: }
! 429:
! 430: /* Go through all the doors */
! 431: else for (exitptr = rer->r_exit; exitptr; exitptr = next(exitptr)) {
! 432: exit = DOORPTR(exitptr);
! 433: exity = exit->y;
! 434: exitx = exit->x;
! 435:
! 436: /* Make sure it is a real door */
! 437: dch = CCHAR( mvwinch(stdscr, exity, exitx) );
! 438: if (dch == PASSAGE || dch == DOOR) {
! 439: /* Don't count a door if we are fleeing from someone and
! 440: * he is standing on it. Also, don't count it if he is
! 441: * standing in the doorway.
! 442: */
! 443: if (flee) {
! 444: if (ce(*exit, *th->t_dest)) continue;
! 445:
! 446: entrance = doorway(rer, exit);
! 447: if (entrance != NULL && ce(*entrance, *th->t_dest))
! 448: continue;
! 449: }
! 450:
! 451: /* Were we just on this door? */
! 452: if (ce(*exit, th->t_oldpos)) last_door = exit;
! 453:
! 454: else {
! 455: dist = DISTANCE(th->t_dest->y, th->t_dest->x, exity, exitx);
! 456:
! 457: /* If fleeing, we want to maximize distance from door to
! 458: * what we flee, and minimize distance from door to us.
! 459: */
! 460: if (flee)
! 461: dist -= DISTANCE(th->t_pos.y, th->t_pos.x, exity, exitx);
! 462:
! 463: /* Maximize distance if fleeing, otherwise minimize it */
! 464: if ((flee && (dist > maxdist)) ||
! 465: (!flee && (dist < mindist))) {
! 466: th->t_doorgoal = exit; /* Use this door */
! 467: this = *exit;
! 468: mindist = maxdist = dist;
! 469: }
! 470: }
! 471: }
! 472: }
! 473:
! 474: /* Could we not find a door? */
! 475: if (dist == MININT) {
! 476: /* If we were on a door, go ahead and use it */
! 477: if (last_door) {
! 478: th->t_doorgoal = last_door;
! 479: this = th->t_oldpos;
! 480: dist = 0; /* Indicate that we found a door */
! 481: }
! 482: else th->t_doorgoal = NULL; /* No more door goal */
! 483: }
! 484:
! 485: /* Indicate that we do not want to flee from the door */
! 486: if (dist != MININT) flee = FALSE;
! 487: }
! 488: else th->t_doorgoal = 0; /* Not going to any door */
! 489:
! 490: /* Now select someplace to go and start the action */
! 491: chase(th, &this, rer, ree, flee);
! 492: }
! 493:
! 494: /*
! 495: * m_sonic:
! 496: * The monster is sounding a sonic blast.
! 497: */
! 498:
! 499: void
! 500: m_sonic(struct thing *tp)
! 501: {
! 502: register int damage;
! 503: static struct object blast =
! 504: {
! 505: MISSILE, {0, 0}, "", 0, "", "150" , NULL, 0, 0, 0, 0
! 506: };
! 507:
! 508: turn_off(*tp, CANSONIC);
! 509: turn_off(*tp, CANSURPRISE);
! 510: do_motion(&blast, tp->t_newpos.y, tp->t_newpos.x, tp);
! 511: damage = 150;
! 512: if (save(VS_BREATH, &player, -3))
! 513: damage /= 2;
! 514: msg ("%s's sonic blast hits you", prname(monster_name(tp), TRUE));
! 515: if ((pstats.s_hpt -= damage) <= 0)
! 516: death(tp->t_index);
! 517:
! 518: running = FALSE;
! 519: if (fight_flush) md_flushinp();
! 520: dsrpt_player();
! 521: }
! 522:
! 523: /*
! 524: * m_spell:
! 525: * The monster casts a spell. Currently this is limited to
! 526: * magic missile.
! 527: */
! 528: void
! 529: m_spell(struct thing *tp)
! 530: {
! 531: static struct object missile =
! 532: {
! 533: MISSILE, {0, 0}, "", 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
! 534: };
! 535:
! 536: sprintf(missile.o_hurldmg, "%dd4", tp->t_stats.s_lvl);
! 537: do_motion(&missile, tp->t_newpos.y, tp->t_newpos.x, tp);
! 538: hit_monster(unc(missile.o_pos), &missile, tp);
! 539: turn_off(*tp, CANMISSILE);
! 540: turn_off(*tp, CANSURPRISE);
! 541:
! 542: running = FALSE;
! 543: if (fight_flush) md_flushinp();
! 544: }
! 545:
! 546: /*
! 547: * m_summon:
! 548: * Summon aid.
! 549: */
! 550:
! 551: void
! 552: m_summon(struct thing *tp)
! 553: {
! 554: register char *helpname, *mname;
! 555: int fail, numsum;
! 556: register int which, i;
! 557:
! 558: /* Let's make sure our prey is still here */
! 559: if (!cansee(unc(tp->t_pos)) || fallpos(&hero, FALSE, 2) == NULL) return;
! 560:
! 561: /*
! 562: * Non-uniques can only summon once. Uniques get fewer
! 563: * creatures with each successive summoning. Also, the
! 564: * probability of summoning goes down
! 565: */
! 566: if (off(*tp, ISUNIQUE))
! 567: turn_off(*tp, CANSUMMON);
! 568:
! 569: turn_off(*tp, CANSURPRISE);
! 570: mname = monster_name(tp);
! 571: helpname = monsters[tp->t_index].m_typesum;
! 572: which = findmindex(helpname);
! 573:
! 574: if ((off(*tp, ISINVIS) || on(player, CANSEE)) &&
! 575: (off(*tp, ISSHADOW) || on(player, CANSEE)) &&
! 576: (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT))) {
! 577: if (monsters[which].m_normal == FALSE) { /* genocided? */
! 578: msg("%s appears dismayed", prname(mname, TRUE));
! 579: monsters[tp->t_index].m_numsum = 0;
! 580: }
! 581: else {
! 582: msg("%s summons %ss for help", prname(mname, TRUE), helpname);
! 583: }
! 584: }
! 585: else {
! 586: if (monsters[which].m_normal == FALSE) /* genocided? */
! 587: monsters[tp->t_index].m_numsum = 0;
! 588: else {
! 589: msg("%ss seem to appear from nowhere!", helpname);
! 590: }
! 591: }
! 592: numsum = monsters[tp->t_index].m_numsum;
! 593: if (numsum && on(*tp, ISUNIQUE)) { /* UNIQUEs summon less each time */
! 594: monsters[tp->t_index].m_numsum--;
! 595: tp->t_summon *= 2; /* cut probability in half */
! 596: }
! 597:
! 598: /*
! 599: * try to make all the creatures around player but remember
! 600: * if unsuccessful
! 601: */
! 602: for (i=0, fail=0; i<numsum; i++) {
! 603: if (!creat_mons(&player, which, FALSE))
! 604: fail++; /* remember the failures */
! 605: }
! 606:
! 607: /*
! 608: * try once again to make the buggers
! 609: */
! 610: for (i=0; i<fail; i++)
! 611: creat_mons(tp, which, FALSE);
! 612:
! 613: /* Now let the poor fellow see all the trouble */
! 614: light(&hero);
! 615: turn_on(*tp, HASSUMMONED);
! 616: }
! 617:
! 618: /*
! 619: * m_use_it:
! 620: * See if the monster (tp) has anything useful it can do
! 621: * (ie. an ability or a weapon) other than just move.
! 622: */
! 623:
! 624: bool
! 625: m_use_it(struct thing *tp, bool flee, struct room *rer, struct room *ree)
! 626: {
! 627: int dist;
! 628: register coord *ee = tp->t_dest, *er = &tp->t_pos;
! 629: coord *shoot_dir;
! 630: struct linked_list *weapon;
! 631: struct thing *prey;
! 632: bool dest_player; /* Are we after the player? */
! 633:
! 634: /*
! 635: * If we are fleeing, there's a chance, depending on our
! 636: * intelligence, that we'll just run in terror.
! 637: */
! 638: if (flee && rnd(25) >= tp->t_stats.s_intel) return(FALSE);
! 639:
! 640: /*
! 641: * Make sure that we have a living destination, and record whether
! 642: * it is the player.
! 643: */
! 644: if (ee != NULL) {
! 645: if (ce(*ee, hero)) {
! 646: dest_player = TRUE;
! 647: prey = &player;
! 648: }
! 649: else {
! 650: struct linked_list *item;
! 651:
! 652: dest_player = FALSE;
! 653:
! 654: /* What is the monster we're chasing? */
! 655: item = find_mons(ee->y, ee->x);
! 656: if (item != NULL) prey = THINGPTR(item);
! 657: else return(FALSE);
! 658: }
! 659: }
! 660: else return(FALSE);
! 661:
! 662: /*
! 663: * If we are friendly to the hero, we don't do anything.
! 664: */
! 665: if (on(*tp, ISFRIENDLY) && dest_player) return(FALSE);
! 666:
! 667: /*
! 668: * Also, for now, if our prey is in a wall, we won't do
! 669: * anything. The prey must be in the same room as we are OR
! 670: * we must have a straight shot at him. Note that
! 671: * shoot_dir must get set before rer is checked so
! 672: * that we get a valid value.
! 673: */
! 674: if (on(*prey, ISINWALL) ||
! 675: ((shoot_dir = can_shoot(er, ee)) == NULL &&
! 676: (rer == NULL || rer != ree)))
! 677: return(FALSE);
! 678:
! 679: /*
! 680: * If we can't see the prey then forget it
! 681: */
! 682: if (on(*prey, ISINVIS) && off(*tp, CANSEE))
! 683: return(FALSE);
! 684:
! 685: /* How far are we from our prey? */
! 686: dist = DISTANCE(er->y, er->x, ee->y, ee->x);
! 687:
! 688: /*
! 689: * Shall we summon aid so we don't have to get our hands dirty?
! 690: * For now, we will only summon aid against the player.
! 691: * We'll wait until he's within 2 dots of a missile length.
! 692: */
! 693: if (on(*tp, CANSUMMON) && dest_player &&
! 694: dist < (BOLT_LENGTH+2)*(BOLT_LENGTH+2) &&
! 695: rnd(tp->t_summon) < tp->t_stats.s_lvl &&
! 696: monsters[tp->t_index].m_numsum > 0 &&
! 697: fallpos(&hero, FALSE, 2) != NULL) {
! 698: tp->t_action = A_SUMMON; /* We're going to summon help */
! 699: tp->t_no_move = movement(tp); /* It takes time! */
! 700: return(TRUE);
! 701: }
! 702:
! 703: /*
! 704: * If the creature can cast a slow spell and if the prey is within
! 705: * 2 dots of a missile fire, then see whether we will cast it.
! 706: * if next to player, lessen chance because we don't like being
! 707: * disrupted
! 708: */
! 709: if (on(*tp, CANSLOW) && dest_player &&
! 710: dist < (BOLT_LENGTH+5)*(BOLT_LENGTH+5) &&
! 711: rnd(100) < (dist > 3 ? tp->t_cast : tp->t_cast/2)) {
! 712: tp->t_action = A_SLOW; /* We're going to slow him */
! 713: tp->t_no_move = 3 * movement(tp); /* Takes time! */
! 714: debug("casting slow spell!");
! 715: return(TRUE);
! 716: }
! 717:
! 718: /*
! 719: * If we have a special magic item, we might use it. We will restrict
! 720: * this options to uniques with relics and creatures with wands for now.
! 721: * Also check for the quartermaster. Don't want him shooting wands....
! 722: */
! 723: if ((on(*tp, ISUNIQUE) || on(*tp, CARRYSTICK)) &&
! 724: off(*tp, CANSELL) && dest_player &&
! 725: m_use_pack(tp, er, ee, dist, shoot_dir)) {
! 726: return(TRUE);
! 727: }
! 728:
! 729: /* From now on, we must have a direct shot at the prey */
! 730: if (shoot_dir == NULL) return(FALSE);
! 731:
! 732: /* We may use a sonic blast if we can, only on the player */
! 733: if (on(*tp, CANSONIC) &&
! 734: dest_player &&
! 735: (dist < BOLT_LENGTH*2) &&
! 736: (rnd(100) < tp->t_breathe)) {
! 737: tp->t_newpos = *shoot_dir; /* Save the direction */
! 738: tp->t_action = A_SONIC; /* We're going to sonic blast */
! 739: tp->t_no_move = 2 * movement(tp); /* Takes 2 movement periods */
! 740: }
! 741:
! 742: /* If we can breathe, we may do so */
! 743: else if (on(*tp, CANBREATHE) &&
! 744: (dist < BOLT_LENGTH*BOLT_LENGTH) &&
! 745: (rnd(100) < tp->t_breathe)) {
! 746: tp->t_newpos = *shoot_dir; /* Save the direction */
! 747: tp->t_action = A_BREATHE; /* We're going to breathe */
! 748: tp->t_no_move = movement(tp); /* It takes 1 movement period */
! 749: }
! 750:
! 751: /*
! 752: * We may shoot missiles if we can
! 753: * if next to player, lessen chance so we don't get disrupted as often
! 754: */
! 755: else if (on(*tp,CANMISSILE) &&
! 756: rnd(100) < (dist > 3 ? tp->t_cast : tp->t_cast/2)){
! 757: tp->t_newpos = *shoot_dir; /* Save the direction */
! 758: tp->t_action = A_MISSILE; /* We're going to shoot MM's */
! 759: tp->t_no_move = 3 * movement(tp); /* Takes time! */
! 760: }
! 761:
! 762: /*
! 763: * If we can shoot or throw something, we might do so.
! 764: * If next to player, then forget it
! 765: */
! 766: else if ((on(*tp,CANSHOOT) || on(*tp,CARRYWEAPON) ||
! 767: on(*tp,CARRYDAGGER) || on(*tp, CARRYAXE)) &&
! 768: dist > 3 &&
! 769: off(*tp, CANSELL) &&
! 770: (weapon = get_hurl(tp))) {
! 771: tp->t_newpos = *shoot_dir; /* Save the direction */
! 772: tp->t_action = A_THROW; /* We're going to throw something */
! 773: tp->t_using = weapon; /* Save our weapon */
! 774: tp->t_no_move = 2 * movement(tp); /* Takes 2 movement periods */
! 775: }
! 776:
! 777: /* We couldn't find anything to do */
! 778: else return(FALSE);
! 779:
! 780: return(TRUE);
! 781:
! 782: }
! 783:
! 784: /*
! 785: * runners:
! 786: * Make all the awake monsters try to do something.
! 787: * segments: Number of segments since last called
! 788: */
! 789:
! 790: int
! 791: runners(int segments)
! 792: {
! 793: register struct linked_list *item;
! 794: register struct thing *tp = NULL;
! 795: register int min_time = 20; /* Minimum time until a monster can act */
! 796:
! 797: /*
! 798: * loop thru the list of running (wandering) monsters and see what
! 799: * each one will do this time.
! 800: *
! 801: * Note: the special case that one of this buggers kills another.
! 802: * if this happens than we have to see if the monster killed
! 803: * himself or someone else. In case its himself we have to get next
! 804: * one immediately. If it wasn't we have to get next one at very
! 805: * end in case he killed the next one.
! 806: */
! 807:
! 808: for (item = mlist; item != NULL; item = next(item)) {
! 809: tp = THINGPTR(item);
! 810: turn_on(*tp, ISREADY);
! 811: }
! 812:
! 813: for (;;) {
! 814:
! 815: for (item = mlist; item != NULL; item = next(item)) {
! 816: tp = THINGPTR(item);
! 817:
! 818: if (on(*tp, ISREADY))
! 819: break;
! 820: }
! 821:
! 822: if (item == NULL)
! 823: break;
! 824:
! 825: turn_off(*tp, ISREADY);
! 826:
! 827: /* If we are not awake, just skip us */
! 828: if (off(*tp, ISRUN) && off(*tp, ISHELD)) continue;
! 829:
! 830: /* See if it's our turn */
! 831: tp->t_no_move -= segments;
! 832: if (tp->t_no_move > 0) {
! 833: if (tp->t_no_move < min_time) min_time = tp->t_no_move;
! 834: continue;
! 835: }
! 836:
! 837: /* If we were frozen, we're moving now */
! 838: if (tp->t_action == A_FREEZE) tp->t_action = A_NIL;
! 839:
! 840: if (on(*tp, ISHELD)) {
! 841: /* Make sure the action and using are nil */
! 842: tp->t_action = A_NIL;
! 843: tp->t_using = NULL;
! 844:
! 845: /* Can we break free? */
! 846: if (rnd(tp->t_stats.s_lvl) > 11) {
! 847: turn_off(*tp, ISHELD);
! 848: runto(tp, &hero);
! 849: if (cansee(tp->t_pos.y, tp->t_pos.x))
! 850: msg("%s breaks free from the hold spell",
! 851: prname(monster_name(tp), TRUE));
! 852: }
! 853:
! 854: /* Too bad -- try again later */
! 855: else tp->t_no_move = movement(tp);
! 856: }
! 857:
! 858: /* Heal the creature if it's not in the middle of some action */
! 859: if (tp->t_action == A_NIL) doctor(tp);
! 860:
! 861: while (off(*tp,ISELSEWHERE) &&
! 862: off(*tp,ISDEAD) &&
! 863: tp->t_no_move <= 0 && off(*tp, ISHELD) && on(*tp, ISRUN)) {
! 864: /* Let's act (or choose an action if t_action = A_NIL) */
! 865: m_act(tp);
! 866: }
! 867:
! 868: if (off(*tp,ISELSEWHERE) && off(*tp,ISDEAD)) {
! 869: if (tp->t_no_move < min_time) min_time = tp->t_no_move;
! 870: if (tp->t_quiet < 0) tp->t_quiet = 0;
! 871: }
! 872: }
! 873: return(min_time);
! 874: }
! 875:
! 876: /*
! 877: * See if a monster has some magic it can use. Return TRUE if so.
! 878: * Only care about relics and wands for now.
! 879: */
! 880: bool
! 881: m_use_pack(struct thing *monster, coord *monst_pos, coord *defend_pos,
! 882: int dist, coord *shoot_dir)
! 883: {
! 884: register struct object *obj;
! 885: register struct linked_list *pitem, *relic, *stick;
! 886: register int units = -1;
! 887:
! 888: relic = stick = NULL;
! 889:
! 890: for (pitem=monster->t_pack; pitem; pitem=next(pitem)) {
! 891: obj = OBJPTR(pitem);
! 892: if (obj->o_flags & ISCURSED) continue;
! 893: if (obj->o_type == RELIC) {
! 894: switch (obj->o_which) {
! 895: case MING_STAFF:
! 896: if (shoot_dir != NULL) {
! 897: units = 2; /* Use 2 time units */
! 898: relic = pitem;
! 899: }
! 900:
! 901: when EMORI_CLOAK:
! 902: if (obj->o_charges != 0 &&
! 903: shoot_dir != NULL) {
! 904: units = 2; /* Use 2 time units */
! 905: relic = pitem;
! 906: }
! 907:
! 908: when ASMO_ROD:
! 909: /* The bolt must be able to reach the defendant */
! 910: if (shoot_dir != NULL &&
! 911: dist < BOLT_LENGTH * BOLT_LENGTH) {
! 912: units = 2; /* Use 2 time units */
! 913: relic = pitem;
! 914: }
! 915:
! 916: when BRIAN_MANDOLIN:
! 917: /* The defendant must be the player and within 4 spaces */
! 918: if (ce(*defend_pos, hero) &&
! 919: dist < 25 &&
! 920: player.t_action != A_FREEZE) {
! 921: units = 4;
! 922: relic = pitem;
! 923: }
! 924:
! 925: when GERYON_HORN:
! 926: /* The defendant must be the player and within 5 spaces */
! 927: if (ce(*defend_pos, hero) &&
! 928: dist < 25 &&
! 929: (off(player,ISFLEE)|| player.t_dest!=&monster->t_pos)) {
! 930: units = 3;
! 931: relic = pitem;
! 932: }
! 933: }
! 934: }
! 935: if (obj->o_type == STICK) {
! 936: if (obj->o_charges < 1) continue;
! 937: switch(obj->o_which) {
! 938: case WS_ELECT:
! 939: case WS_FIRE:
! 940: case WS_COLD:
! 941: /* The bolt must be able to reach the defendant */
! 942: if (shoot_dir != NULL &&
! 943: dist < BOLT_LENGTH * BOLT_LENGTH) {
! 944: units = 3;
! 945: stick = pitem;
! 946: }
! 947:
! 948: when WS_MISSILE:
! 949: case WS_SLOW_M:
! 950: case WS_CONFMON:
! 951: case WS_PARALYZE:
! 952: case WS_MDEG:
! 953: case WS_FEAR:
! 954: if (shoot_dir != NULL) {
! 955: units = 3;
! 956: stick = pitem;
! 957: }
! 958:
! 959: otherwise:
! 960: break;
! 961: }
! 962: }
! 963: }
! 964:
! 965: /* use relics in preference to all others */
! 966: if (relic) debug("chance to use relic = %d%%", monster->t_artifact);
! 967: if (stick) debug("chance to use stick = %d%%", monster->t_wand);
! 968: if (relic && rnd(100) < monster->t_artifact) {
! 969: monster->t_action = A_USERELIC;
! 970: pitem = relic;
! 971: }
! 972: else if (stick && rnd(100) < monster->t_wand) {
! 973: /*
! 974: * see if the monster will use the wand
! 975: */
! 976: pitem = stick;
! 977: monster->t_action = A_USEWAND;
! 978: }
! 979: else {
! 980: return(FALSE);
! 981: }
! 982:
! 983: monster->t_no_move = units * movement(monster);
! 984: monster->t_using = pitem;
! 985: monster->t_newpos = *shoot_dir;
! 986: return(TRUE);
! 987: }
CVSweb