Mercurial > hg > early-roguelike
diff rogue3/monsters.c @ 0:527e2150eaf0
Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Tue, 13 Oct 2009 13:33:34 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/monsters.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,243 @@ +/* + * File with various monster functions in it + * + * @(#)monsters.c 3.18 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 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 "rogue.h" +#include <string.h> +#include <ctype.h> + +/* + * List of monsters in rough order of vorpalness + */ +char lvl_mons[27] = "KJBSHEAOZGLCRQNYTWFIXUMVDP"; +char wand_mons[27] = "KJBSH AOZG CRQ Y W IXU V "; + +/* + * randmonster: + * Pick a monster to show up. The lower the level, + * the meaner the monster. + */ + +int +randmonster(int wander) +{ + int d; + 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 + */ + +void +new_monster(struct linked_list *item, int type, coord *cp) +{ + struct thing *tp; + struct monster *mp; + + attach(mlist, item); + tp = (struct thing *) ldata(item); + tp->t_type = type; + tp->t_pos = *cp; + tp->t_oldch = mvwinch(cw, cp->y, cp->x); + mvwaddch(mw, cp->y, cp->x, tp->t_type); + mp = &monsters[tp->t_type-'A']; + tp->t_stats.s_hpt = roll(mp->m_stats.s_lvl, 8); + tp->t_stats.s_lvl = mp->m_stats.s_lvl; + tp->t_stats.s_arm = mp->m_stats.s_arm; + strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg); + tp->t_stats.s_exp = mp->m_stats.s_exp; + tp->t_stats.s_str.st_str = 10; + tp->t_flags = mp->m_flags; + tp->t_turn = TRUE; + tp->t_pack = NULL; + if (ISWEARING(R_AGGR)) + runto(cp, &hero); + if (type == 'M') + { + int mch = 0; + + if (tp->t_pack != NULL) + mch = ((struct object *) ldata(tp->t_pack))->o_type; + else + switch (rnd(level > 25 ? 9 : 8)) + { + case 0: mch = GOLD; + when 1: mch = POTION; + when 2: mch = SCROLL; + when 3: mch = STAIRS; + when 4: mch = WEAPON; + when 5: mch = ARMOR; + when 6: mch = RING; + when 7: mch = STICK; + when 8: mch = AMULET; + } + tp->t_disguise = mch; + } +} + +/* + * wanderer: + * A wandering monster has awakened and is headed for the player + */ + +void +wanderer() +{ + int i, ch; + struct room *rp, *hr = roomin(&hero); + struct linked_list *item; + struct thing *tp; + coord cp; + + item = new_item(sizeof *tp); + do + { + i = rnd_room(); + if ((rp = &rooms[i]) == hr) + continue; + rnd_pos(rp, &cp); + if ((ch = mvwinch(stdscr, cp.y, cp.x)) == ERR) + { + debug("Routine wanderer: mvwinch failed to %d,%d", cp.y, cp.x); + if (wizard) + wait_for(cw,'\n'); + return; + } + } until(hr != rp && step_ok(ch)); + new_monster(item, randmonster(TRUE), &cp); + tp = (struct thing *) ldata(item); + tp->t_flags |= ISRUN; + tp->t_pos = cp; + tp->t_dest = &hero; + if (wizard) + msg("Started a wandering %s", monsters[tp->t_type-'A'].m_name); +} + +/* + * what to do when the hero steps next to a monster + */ +struct linked_list * +wake_monster(int y, int x) +{ + struct thing *tp; + struct linked_list *it; + struct room *rp; + int ch; + + if ((it = find_mons(y, x)) == NULL) + { + fatal("Can't find monster in wake"); + return NULL; + } + + tp = (struct thing *) ldata(it); + ch = tp->t_type; + /* + * Every time he sees mean monster, it might start chasing him + */ + if (rnd(100) > 33 && on(*tp, ISMEAN) && off(*tp, ISHELD) + && !ISWEARING(R_STEALTH)) + { + tp->t_dest = &hero; + tp->t_flags |= ISRUN; + } + if (ch == 'U' && off(player, ISBLIND)) + { + rp = roomin(&hero); + if ((rp != NULL && !(rp->r_flags&ISDARK)) + || DISTANCE(y, x, hero.y, hero.x) < 3) + { + if (off(*tp, ISFOUND) && !save(VS_MAGIC)) + { + msg("The umber hulk's gaze has confused you."); + if (on(player, ISHUH)) + lengthen(unconfuse, rnd(20)+HUHDURATION); + else + fuse(unconfuse, 0, rnd(20)+HUHDURATION, AFTER); + player.t_flags |= ISHUH; + } + tp->t_flags |= ISFOUND; + } + } + /* + * Hide invisible monsters + */ + if (on(*tp, ISINVIS) && off(player, CANSEE)) + ch = mvwinch(stdscr, y, x); + /* + * Let greedy ones guard gold + */ + if (on(*tp, ISGREED) && off(*tp, ISRUN)) + { + rp = roomin(&hero); + + if (rp != NULL && rp->r_goldval) + { + tp->t_dest = &rp->r_gold; + tp->t_flags |= ISRUN; + } + } + + return it; +} + +void +genocide() +{ + struct linked_list *ip; + struct thing *mp; + int c; + int i; + struct linked_list *nip; + + addmsg("Which monster"); + if (!terse) + addmsg(" do you wish to wipe out"); + msg("? "); + while (!isalpha(c = readchar(cw))) + if (c == ESCAPE) + return; + else + { + mpos = 0; + msg("Please specify a letter between 'A' and 'Z'"); + } + if (islower(c)) + c = toupper(c); + for (ip = mlist; ip; ip = nip) + { + mp = (struct thing *) ldata(ip); + nip = next(ip); + if (mp->t_type == c) + remove_monster(&mp->t_pos, ip); + } + for (i = 0; i < 26; i++) + if (lvl_mons[i] == c) + { + lvl_mons[i] = ' '; + wand_mons[i] = ' '; + break; + } +}