Mercurial > hg > early-roguelike
diff rogue4/monsters.c @ 12:9535a08ddc39
Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Sat, 24 Oct 2009 16:52:52 +0000 |
parents | |
children | 1b73a8641b37 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/monsters.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,278 @@ +/* + * File with various monster functions in it + * + * @(#)monsters.c 4.24 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include <curses.h> +#include <string.h> +#include <ctype.h> +#include "rogue.h" + +/* + * List of monsters in rough order of vorpalness + * + * NOTE: This not initialized using strings so that xstr doesn't set up + * the string not to be saved. Otherwise genocide is lost through + * saving a game. + */ +char lvl_mons[] = { + 'K', 'J', 'B', 'S', 'H', 'E', 'A', 'O', 'Z', 'G', 'L', 'C', 'R', + 'Q', 'N', 'Y', 'T', 'W', 'F', 'I', 'X', 'U', 'M', 'V', 'P', 'D', + '\0' +}; + +char wand_mons[] = { + 'K', 'J', 'B', 'S', 'H', ' ', 'A', 'O', 'Z', 'G', ' ', 'C', 'R', + 'Q', ' ', 'Y', 'T', 'W', ' ', 'I', 'X', 'U', ' ', 'V', 'P', ' ', + '\0' +}; + +/* + * randmonster: + * Pick a monster to show up. The lower the level, + * the meaner the monster. + */ +randmonster(wander) +bool wander; +{ + register int d; + register char *mons; + + mons = wander ? wand_mons : lvl_mons; + do + { + d = level + (rnd(10) - 5); + if (d < 1) + d = rnd(5) + 1; + if (d > 26) + d = rnd(5) + 22; + } while (mons[--d] == ' '); + return mons[d]; +} + +/* + * new_monster: + * Pick a new monster and add it to the list + */ +new_monster(tp, type, cp) +register THING *tp; +char type; +register coord *cp; +{ + register struct monster *mp; + register int lev_add; + + if ((lev_add = level - AMULETLEVEL) < 0) + lev_add = 0; + attach(mlist, tp); + tp->t_type = type; + tp->t_disguise = type; + tp->t_pos = *cp; + tp->t_oldch = mvinch(cp->y, cp->x); + tp->t_room = roomin(cp); + moat(cp->y, cp->x) = tp; + mp = &monsters[tp->t_type-'A']; + tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add; + tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8); + tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add; + strncpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg,16); + tp->t_stats.s_str = mp->m_stats.s_str; + tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp); + tp->t_flags = mp->m_flags; + tp->t_turn = TRUE; + tp->t_pack = NULL; + if (ISWEARING(R_AGGR)) + runto(cp, &hero); + if (type == 'M') + switch (rnd(level > 25 ? 9 : 8)) + { + case 0: tp->t_disguise = GOLD; + when 1: tp->t_disguise = POTION; + when 2: tp->t_disguise = SCROLL; + when 3: tp->t_disguise = STAIRS; + when 4: tp->t_disguise = WEAPON; + when 5: tp->t_disguise = ARMOR; + when 6: tp->t_disguise = RING; + when 7: tp->t_disguise = STICK; + when 8: tp->t_disguise = AMULET; + } +} + +/* + * expadd: + * Experience to add for this monster's level/hit points + */ +exp_add(tp) +register THING *tp; +{ + register int mod; + + if (tp->t_stats.s_lvl == 1) + mod = tp->t_stats.s_maxhp / 8; + else + mod = tp->t_stats.s_maxhp / 6; + if (tp->t_stats.s_lvl > 9) + mod *= 20; + else if (tp->t_stats.s_lvl > 6) + mod *= 4; + return mod; +} + +/* + * wanderer: + * Create a new wandering monster and aim it at the player + */ +wanderer() +{ + register int i; + register struct room *rp; + register THING *tp; + coord cp = {0,0}; + register int cnt = 0; + + tp = new_item(); + do + { + /* Avoid endless loop when all rooms are filled with monsters + * and the player room is not accessible to the monsters. + */ + if (cnt++ >= 500) + { + discard(tp); + return; + } + i = rnd_room(); + if ((rp = &rooms[i]) == proom) + continue; + rnd_pos(rp, &cp); + } until (rp != proom && step_ok(winat(cp.y, cp.x))); + new_monster(tp, randmonster(TRUE), &cp); + runto(&tp->t_pos, &hero); +#ifdef WIZARD + if (wizard) + msg("started a wandering %s", monsters[tp->t_type-'A'].m_name); +#endif +} + +/* + * wake_monster: + * What to do when the hero steps next to a monster + */ +THING * +wake_monster(y, x) +int y, x; +{ + register THING *tp; + register struct room *rp; + register char ch; + +#ifdef WIZARD + if ((tp = moat(y, x)) == NULL) + msg("can't find monster in wake_monster"); +#else + tp = moat(y, x); +#endif + ch = tp->t_type; + /* + * Every time he sees mean monster, it might start chasing him + */ + if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD) + && !ISWEARING(R_STEALTH)) + { + tp->t_dest = &hero; + tp->t_flags |= ISRUN; + } + if (ch == 'U' && !on(player, ISBLIND) && !on(*tp, ISFOUND) + && !on(*tp, ISCANC) && on(*tp, ISRUN)) + { + rp = proom; + if ((rp != NULL && !(rp->r_flags & ISDARK)) + || DISTANCE(y, x, hero.y, hero.x) < LAMPDIST) + { + tp->t_flags |= ISFOUND; + if (!save(VS_MAGIC)) + { + if (on(player, ISHUH)) + lengthen(unconfuse, rnd(20) + HUHDURATION); + else + fuse(unconfuse, 0, rnd(20) + HUHDURATION, AFTER); + player.t_flags |= ISHUH; + msg("the umber hulk's gaze has confused you"); + } + } + } + /* + * Let greedy ones guard gold + */ + if (on(*tp, ISGREED) && !on(*tp, ISRUN)) + { + tp->t_flags |= ISRUN; + if (proom->r_goldval) + tp->t_dest = &proom->r_gold; + else + tp->t_dest = &hero; + } + return tp; +} + +/* + * genocide: + * Wipe one monster out of existence (for now...) + */ +genocide() +{ + register THING *mp; + register char c; + register int i; + register THING *nmp; + + addmsg("which monster"); + if (!terse) + addmsg(" do you wish to wipe out"); + msg("? "); + while (!isalpha(c = readchar())) + if (c == ESCAPE) + return; + else + { + mpos = 0; + msg("please specifiy a letter between 'A' and 'Z'"); + } + mpos = 0; + if (islower(c)) + c = toupper(c); + for (mp = mlist; mp; mp = nmp) + { + nmp = next(mp); + if (mp->t_type == c) + remove_monster(&mp->t_pos, mp, FALSE); + } + for (i = 0; i < 26; i++) + if (lvl_mons[i] == c) + { + lvl_mons[i] = ' '; + wand_mons[i] = ' '; + break; + } + if (!terse) + addmsg("there will be "); + msg("no more %ss", monsters[c - 'A'].m_name); +} + +/* + * give_pack: + * Give a pack to a monster if it deserves one + */ +give_pack(tp) +register THING *tp; +{ + if (rnd(100) < monsters[tp->t_type-'A'].m_carry) + attach(tp->t_pack, new_thing()); +}