Annotation of early-roguelike/rogue4/monsters.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * File with various monster functions in it
! 3: *
! 4: * @(#)monsters.c 4.24 (Berkeley) 4/6/82
! 5: *
! 6: * Rogue: Exploring the Dungeons of Doom
! 7: * Copyright (C) 1980, 1981, 1982 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 <ctype.h>
! 16: #include "rogue.h"
! 17:
! 18: int exp_add(THING *tp);
! 19:
! 20: /*
! 21: * List of monsters in rough order of vorpalness
! 22: *
! 23: * NOTE: This not initialized using strings so that xstr doesn't set up
! 24: * the string not to be saved. Otherwise genocide is lost through
! 25: * saving a game.
! 26: */
! 27: char lvl_mons[] = {
! 28: 'K', 'J', 'B', 'S', 'H', 'E', 'A', 'O', 'Z', 'G', 'L', 'C', 'R',
! 29: 'Q', 'N', 'Y', 'T', 'W', 'F', 'I', 'X', 'U', 'M', 'V', 'P', 'D',
! 30: '\0'
! 31: };
! 32:
! 33: char wand_mons[] = {
! 34: 'K', 'J', 'B', 'S', 'H', ' ', 'A', 'O', 'Z', 'G', ' ', 'C', 'R',
! 35: 'Q', ' ', 'Y', 'T', 'W', ' ', 'I', 'X', 'U', ' ', 'V', 'P', ' ',
! 36: '\0'
! 37: };
! 38:
! 39: /*
! 40: * randmonster:
! 41: * Pick a monster to show up. The lower the level,
! 42: * the meaner the monster.
! 43: */
! 44: char
! 45: randmonster(bool wander)
! 46: {
! 47: register int d;
! 48: register char *mons;
! 49:
! 50: mons = wander ? wand_mons : lvl_mons;
! 51: do
! 52: {
! 53: d = level + (rnd(10) - 5);
! 54: if (d < 1)
! 55: d = rnd(5) + 1;
! 56: if (d > 26)
! 57: d = rnd(5) + 22;
! 58: } while (mons[--d] == ' ');
! 59: return mons[d];
! 60: }
! 61:
! 62: /*
! 63: * new_monster:
! 64: * Pick a new monster and add it to the list
! 65: */
! 66: void
! 67: new_monster(THING *tp, char type, coord *cp)
! 68: {
! 69: register struct monster *mp;
! 70: register int lev_add;
! 71:
! 72: if ((lev_add = level - AMULETLEVEL) < 0)
! 73: lev_add = 0;
! 74: attach(mlist, tp);
! 75: tp->t_type = type;
! 76: tp->t_disguise = type;
! 77: tp->t_pos = *cp;
! 78: tp->t_oldch = mvinch(cp->y, cp->x);
! 79: tp->t_room = roomin(cp);
! 80: moat(cp->y, cp->x) = tp;
! 81: mp = &monsters[tp->t_type-'A'];
! 82: tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
! 83: tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
! 84: tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
! 85: strncpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg,16);
! 86: tp->t_stats.s_str = mp->m_stats.s_str;
! 87: tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
! 88: tp->t_flags = mp->m_flags;
! 89: tp->t_turn = TRUE;
! 90: tp->t_pack = NULL;
! 91: if (ISWEARING(R_AGGR))
! 92: runto(cp, &hero);
! 93: if (type == 'M')
! 94: switch (rnd(level > 25 ? 9 : 8))
! 95: {
! 96: case 0: tp->t_disguise = GOLD;
! 97: when 1: tp->t_disguise = POTION;
! 98: when 2: tp->t_disguise = SCROLL;
! 99: when 3: tp->t_disguise = STAIRS;
! 100: when 4: tp->t_disguise = WEAPON;
! 101: when 5: tp->t_disguise = ARMOR;
! 102: when 6: tp->t_disguise = RING;
! 103: when 7: tp->t_disguise = STICK;
! 104: when 8: tp->t_disguise = AMULET;
! 105: }
! 106: }
! 107:
! 108: /*
! 109: * expadd:
! 110: * Experience to add for this monster's level/hit points
! 111: */
! 112: int
! 113: exp_add(THING *tp)
! 114: {
! 115: register int mod;
! 116:
! 117: if (tp->t_stats.s_lvl == 1)
! 118: mod = tp->t_stats.s_maxhp / 8;
! 119: else
! 120: mod = tp->t_stats.s_maxhp / 6;
! 121: if (tp->t_stats.s_lvl > 9)
! 122: mod *= 20;
! 123: else if (tp->t_stats.s_lvl > 6)
! 124: mod *= 4;
! 125: return mod;
! 126: }
! 127:
! 128: /*
! 129: * wanderer:
! 130: * Create a new wandering monster and aim it at the player
! 131: */
! 132: void
! 133: wanderer(void)
! 134: {
! 135: register int i;
! 136: register struct room *rp;
! 137: register THING *tp;
! 138: coord cp = {0,0};
! 139: register int cnt = 0;
! 140:
! 141: tp = new_item();
! 142: do
! 143: {
! 144: /* Avoid endless loop when all rooms are filled with monsters
! 145: * and the player room is not accessible to the monsters.
! 146: */
! 147: if (cnt++ >= 500)
! 148: {
! 149: discard(tp);
! 150: return;
! 151: }
! 152: i = rnd_room();
! 153: if ((rp = &rooms[i]) == proom)
! 154: continue;
! 155: rnd_pos(rp, &cp);
! 156: } until (rp != proom && step_ok(winat(cp.y, cp.x)));
! 157: new_monster(tp, randmonster(TRUE), &cp);
! 158: runto(&tp->t_pos, &hero);
! 159: #ifdef WIZARD
! 160: if (wizard)
! 161: msg("started a wandering %s", monsters[tp->t_type-'A'].m_name);
! 162: #endif
! 163: }
! 164:
! 165: /*
! 166: * wake_monster:
! 167: * What to do when the hero steps next to a monster
! 168: */
! 169: THING *
! 170: wake_monster(int y, int x)
! 171: {
! 172: register THING *tp;
! 173: register struct room *rp;
! 174: register char ch;
! 175:
! 176: #ifdef WIZARD
! 177: if ((tp = moat(y, x)) == NULL)
! 178: msg("can't find monster in wake_monster");
! 179: #else
! 180: tp = moat(y, x);
! 181: #endif
! 182: ch = tp->t_type;
! 183: /*
! 184: * Every time he sees mean monster, it might start chasing him
! 185: */
! 186: if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
! 187: && !ISWEARING(R_STEALTH))
! 188: {
! 189: tp->t_dest = &hero;
! 190: tp->t_flags |= ISRUN;
! 191: }
! 192: if (ch == 'U' && !on(player, ISBLIND) && !on(*tp, ISFOUND)
! 193: && !on(*tp, ISCANC) && on(*tp, ISRUN))
! 194: {
! 195: rp = proom;
! 196: if ((rp != NULL && !(rp->r_flags & ISDARK))
! 197: || DISTANCE(y, x, hero.y, hero.x) < LAMPDIST)
! 198: {
! 199: tp->t_flags |= ISFOUND;
! 200: if (!save(VS_MAGIC))
! 201: {
! 202: if (on(player, ISHUH))
! 203: lengthen(unconfuse, rnd(20) + HUHDURATION);
! 204: else
! 205: fuse(unconfuse, 0, rnd(20) + HUHDURATION, AFTER);
! 206: player.t_flags |= ISHUH;
! 207: msg("the umber hulk's gaze has confused you");
! 208: }
! 209: }
! 210: }
! 211: /*
! 212: * Let greedy ones guard gold
! 213: */
! 214: if (on(*tp, ISGREED) && !on(*tp, ISRUN))
! 215: {
! 216: tp->t_flags |= ISRUN;
! 217: if (proom->r_goldval)
! 218: tp->t_dest = &proom->r_gold;
! 219: else
! 220: tp->t_dest = &hero;
! 221: }
! 222: return tp;
! 223: }
! 224:
! 225: /*
! 226: * genocide:
! 227: * Wipe one monster out of existence (for now...)
! 228: */
! 229: void
! 230: genocide(void)
! 231: {
! 232: register THING *mp;
! 233: register char c;
! 234: register int i;
! 235: register THING *nmp;
! 236:
! 237: addmsg("which monster");
! 238: if (!terse)
! 239: addmsg(" do you wish to wipe out");
! 240: msg("? ");
! 241: while (!isalpha(c = readchar()))
! 242: if (c == ESCAPE)
! 243: return;
! 244: else
! 245: {
! 246: mpos = 0;
! 247: msg("please specifiy a letter between 'A' and 'Z'");
! 248: }
! 249: mpos = 0;
! 250: if (islower(c))
! 251: c = toupper(c);
! 252: for (mp = mlist; mp; mp = nmp)
! 253: {
! 254: nmp = next(mp);
! 255: if (mp->t_type == c)
! 256: remove_monster(&mp->t_pos, mp, FALSE);
! 257: }
! 258: for (i = 0; i < 26; i++)
! 259: if (lvl_mons[i] == c)
! 260: {
! 261: lvl_mons[i] = ' ';
! 262: wand_mons[i] = ' ';
! 263: break;
! 264: }
! 265: if (!terse)
! 266: addmsg("there will be ");
! 267: msg("no more %ss", monsters[c - 'A'].m_name);
! 268: }
! 269:
! 270: /*
! 271: * give_pack:
! 272: * Give a pack to a monster if it deserves one
! 273: */
! 274: void
! 275: give_pack(THING *tp)
! 276: {
! 277: if (rnd(100) < monsters[tp->t_type-'A'].m_carry)
! 278: attach(tp->t_pack, new_thing());
! 279: }
CVSweb