Annotation of early-roguelike/rogue5/monsters.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * File with various monster functions in it
! 3: *
! 4: * @(#)monsters.c 4.46 (Berkeley) 02/05/99
! 5: *
! 6: * Rogue: Exploring the Dungeons of Doom
! 7: * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
! 8: * All rights reserved.
! 9: *
! 10: * See the file LICENSE.TXT for full copyright and licensing information.
! 11: */
! 12:
! 13: #include <curses.h>
! 14: #include <string.h>
! 15: #include "rogue.h"
! 16: #include <ctype.h>
! 17:
! 18: /*
! 19: * List of monsters in rough order of vorpalness
! 20: */
! 21: static const int lvl_mons[] = {
! 22: 'K', 'E', 'B', 'S', 'H', 'I', 'R', 'O', 'Z', 'L', 'C', 'Q', 'A',
! 23: 'N', 'Y', 'F', 'T', 'W', 'P', 'X', 'U', 'M', 'V', 'G', 'J', 'D'
! 24: };
! 25:
! 26: static const int wand_mons[] = {
! 27: 'K', 'E', 'B', 'S', 'H', 0, 'R', 'O', 'Z', 0, 'C', 'Q', 'A',
! 28: 0, 'Y', 0, 'T', 'W', 'P', 0, 'U', 'M', 'V', 'G', 'J', 0
! 29: };
! 30:
! 31: /*
! 32: * randmonster:
! 33: * Pick a monster to show up. The lower the level,
! 34: * the meaner the monster.
! 35: */
! 36: int
! 37: randmonster(int wander)
! 38: {
! 39: int d;
! 40: const int *mons;
! 41:
! 42: mons = (wander ? wand_mons : lvl_mons);
! 43: do
! 44: {
! 45: d = level + (rnd(10) - 6);
! 46: if (d < 0)
! 47: d = rnd(5);
! 48: if (d > 25)
! 49: d = rnd(5) + 21;
! 50: } while (mons[d] == 0);
! 51: return mons[d];
! 52: }
! 53:
! 54: /*
! 55: * new_monster:
! 56: * Pick a new monster and add it to the list
! 57: */
! 58:
! 59: void
! 60: new_monster(THING *tp, int type, const coord *cp)
! 61: {
! 62: struct monster *mp;
! 63: int lev_add;
! 64:
! 65: if ((lev_add = level - AMULETLEVEL) < 0)
! 66: lev_add = 0;
! 67: attach(mlist, tp);
! 68: tp->t_type = type;
! 69: tp->t_disguise = type;
! 70: tp->t_pos = *cp;
! 71: move(cp->y, cp->x);
! 72: tp->t_oldch = CCHAR( inch() );
! 73: tp->t_room = roomin(cp);
! 74: moat(cp->y, cp->x) = tp;
! 75: mp = &monsters[tp->t_type-'A'];
! 76: tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
! 77: tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
! 78: tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
! 79: strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg);
! 80: tp->t_stats.s_str = mp->m_stats.s_str;
! 81: tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
! 82: tp->t_flags = mp->m_flags;
! 83: if (level > 29)
! 84: tp->t_flags |= ISHASTE;
! 85: tp->t_turn = TRUE;
! 86: tp->t_pack = NULL;
! 87: if (ISWEARING(R_AGGR))
! 88: runto(cp);
! 89: if (type == 'X')
! 90: tp->t_disguise = rnd_thing();
! 91: }
! 92:
! 93: /*
! 94: * expadd:
! 95: * Experience to add for this monster's level/hit points
! 96: */
! 97: int
! 98: exp_add(const THING *tp)
! 99: {
! 100: int mod;
! 101:
! 102: if (tp->t_stats.s_lvl == 1)
! 103: mod = tp->t_stats.s_maxhp / 8;
! 104: else
! 105: mod = tp->t_stats.s_maxhp / 6;
! 106: if (tp->t_stats.s_lvl > 9)
! 107: mod *= 20;
! 108: else if (tp->t_stats.s_lvl > 6)
! 109: mod *= 4;
! 110: return mod;
! 111: }
! 112:
! 113: /*
! 114: * wanderer:
! 115: * Create a new wandering monster and aim it at the player
! 116: */
! 117:
! 118: void
! 119: wanderer(void)
! 120: {
! 121: THING *tp;
! 122: coord cp;
! 123: int cnt = 0;
! 124:
! 125: tp = new_item();
! 126: do
! 127: {
! 128: /* Avoid endless loop when all rooms are filled with monsters
! 129: * and the player room is not accessible to the monsters.
! 130: */
! 131: if (cnt++ >= 500)
! 132: {
! 133: discard(tp);
! 134: return;
! 135: }
! 136: find_floor(NULL, &cp, FALSE, TRUE);
! 137: } while (roomin(&cp) == proom && moat(cp.y, cp.x) == NULL);
! 138: new_monster(tp, randmonster(TRUE), &cp);
! 139: if (on(player, SEEMONST))
! 140: {
! 141: standout();
! 142: if (!on(player, ISHALU))
! 143: addch(tp->t_type);
! 144: else
! 145: addch(rnd(26) + 'A');
! 146: standend();
! 147: }
! 148: runto(&tp->t_pos);
! 149: #ifdef MASTER
! 150: if (wizard)
! 151: msg("started a wandering %s", monsters[tp->t_type-'A'].m_name);
! 152: #endif
! 153: }
! 154:
! 155: /*
! 156: * wake_monster:
! 157: * What to do when the hero steps next to a monster
! 158: */
! 159: const THING *
! 160: wake_monster(int y, int x)
! 161: {
! 162: THING *tp;
! 163: struct room *rp;
! 164: int ch;
! 165: const char *mname;
! 166:
! 167: if ((tp = moat(y, x)) == NULL) {
! 168: #ifdef MASTER
! 169: msg("can't find monster in wake_monster");
! 170: #endif
! 171: return NULL;
! 172: }
! 173:
! 174: ch = tp->t_type;
! 175: /*
! 176: * Every time he sees mean monster, it might start chasing him
! 177: */
! 178: if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
! 179: && !ISWEARING(R_STEALTH) && !on(player, ISLEVIT))
! 180: {
! 181: tp->t_dest = &hero;
! 182: tp->t_flags |= ISRUN;
! 183: }
! 184: if (ch == 'M' && !on(player, ISBLIND) && !on(player, ISHALU)
! 185: && !on(*tp, ISFOUND) && !on(*tp, ISCANC) && on(*tp, ISRUN))
! 186: {
! 187: rp = proom;
! 188: if ((rp != NULL && !(rp->r_flags & ISDARK))
! 189: || dist(y, x, hero.y, hero.x) < LAMPDIST)
! 190: {
! 191: tp->t_flags |= ISFOUND;
! 192: if (!save(VS_MAGIC))
! 193: {
! 194: if (on(player, ISHUH))
! 195: lengthen(unconfuse, spread(HUHDURATION));
! 196: else
! 197: fuse(unconfuse, 0, spread(HUHDURATION), AFTER);
! 198: player.t_flags |= ISHUH;
! 199: mname = set_mname(tp);
! 200: addmsg("%s", mname);
! 201: if (strcmp(mname, "it") != 0)
! 202: addmsg("'");
! 203: msg("s gaze has confused you");
! 204: }
! 205: }
! 206: }
! 207: /*
! 208: * Let greedy ones guard gold
! 209: */
! 210: if (on(*tp, ISGREED) && !on(*tp, ISRUN))
! 211: {
! 212: tp->t_flags |= ISRUN;
! 213: if (proom->r_goldval)
! 214: tp->t_dest = &proom->r_gold;
! 215: else
! 216: tp->t_dest = &hero;
! 217: }
! 218: return tp;
! 219: }
! 220:
! 221: /*
! 222: * give_pack:
! 223: * Give a pack to a monster if it deserves one
! 224: */
! 225:
! 226: void
! 227: give_pack(THING *tp)
! 228: {
! 229: if (level >= max_level && rnd(100) < monsters[tp->t_type-'A'].m_carry)
! 230: attach(tp->t_pack, new_thing());
! 231: }
! 232:
! 233: /*
! 234: * save_throw:
! 235: * See if a creature save against something
! 236: */
! 237: int
! 238: save_throw(int which, const THING *tp)
! 239: {
! 240: int need;
! 241:
! 242: need = 14 + which - tp->t_stats.s_lvl / 2;
! 243: return (roll(1, 20) >= need);
! 244: }
! 245:
! 246: /*
! 247: * save:
! 248: * See if he saves against various nasty things
! 249: */
! 250: int
! 251: save(int which)
! 252: {
! 253: if (which == VS_MAGIC)
! 254: {
! 255: if (ISRING(LEFT, R_PROTECT))
! 256: which -= cur_ring[LEFT]->o_arm;
! 257: if (ISRING(RIGHT, R_PROTECT))
! 258: which -= cur_ring[RIGHT]->o_arm;
! 259: }
! 260: return save_throw(which, &player);
! 261: }
CVSweb