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;
+	}
+}